设计模式——装饰者模式 Java源代码

来源:互联网 发布:小学多媒体教学软件 编辑:程序博客网 时间:2024/04/28 23:46

装饰者模式,可以动态地把职责附加到已有的对象上面去。又称 Wrapper Pattern,在代码实现的时候,确实有“包装”的意思。

类图

装饰者
图:来自《Head First Design Patterns》

可以看出,装饰者模式里面,有4个角色:Component抽象类,ConcreteComponent具体类,Decorator抽象类,ConcreteDecorator具体类

装饰者模式
图:我的Java源代码的类图

总共10个类
一个Component抽象类
两个ConcreteComponent具体类
一个Decorator抽象类
五个ConcreteDecorator具体类
一个Main测试类

ConcreteDecorator 继承了Decorator抽象类, 组合了Component抽象类。Decorator抽象类继承了Component抽象类,这个继承的目的是:it’s vital that the decorators have the same type as the object they are going to decorate。简而言之,就是为了获得相同的类型,并不是为了获得行为。组合是为了让所有的concreteDecorator可以“互相包装、装饰”


talk is cheap, show me the code

去食堂打菜,经济套餐,假设总共只有5种食物可供选择分别是:手撕包菜,茄子豆角,麻婆豆腐,青椒肉丝,红烧里脊。

一个Component抽象类

package decorator;public abstract class Meal{    String description = "Unknown Meal";    public String getDescription()    {        return description;    }    public abstract double cost();}

两个ConcreteComponent具体类

package decorator;public class ChineseMeal extends Meal{    public ChineseMeal()    {        description = "Chinese Meal";    }    @Override    public double cost()    {        return 1.0;        // 一次性餐具费用    }}
package decorator;public class WesternMeal extends Meal{    public WesternMeal()    {        description = "Western meal";    }    @Override    public double cost()    {        return 5.0;        // 不锈钢刀、叉费用    }}

一个Decorator抽象类

package decorator;public abstract class Decorator extends Meal{    public abstract String getDescription();}

五个ConcreteDecorator具体类

package decorator;// 茄子豆角public class EggplantBean extends Decorator{    Meal meal;    public EggplantBean(Meal meal)    {        this.meal = meal;    }    @Override    public String getDescription()    {        return meal.getDescription() + ", 茄子豆角";    }    @Override    public double cost()    {        return 2 + meal.cost();    }}
package decorator;// 青椒炒肉public class GreenPepperPork extends Decorator{    Meal meal;    public GreenPepperPork(Meal meal)    {        this.meal = meal;    }    @Override    public String getDescription()    {        return meal.getDescription() + ", 青椒炒肉";    }    @Override    public double cost()    {        return 3 + meal.cost();    }}
package decorator;// 手撕包菜public class HandCabbage extends Decorator{    Meal meal;    public HandCabbage(Meal meal)    {        this.meal = meal;    }    @Override    public String getDescription()    {        return meal.getDescription() + ", 手撕包菜";    }    @Override    public double cost()    {        return 2 + meal.cost();    }}
package decorator;// 麻婆豆腐public class MapoTofu extends Decorator{    Meal meal;    public MapoTofu(Meal meal)    {        this.meal = meal;    }    @Override    public String getDescription()    {        return meal.getDescription() + ", 麻婆豆腐";    }    @Override    public double cost()    {        return 4 + meal.cost();    }}
package decorator;// 红烧里脊public class BraiseTenderloin extends Decorator{    Meal meal;    public BraiseTenderloin(Meal meal)    {        this.meal = meal;    }    @Override    public String getDescription()    {        return meal.getDescription() + ", 红烧里脊";    }    @Override    public double cost()    {        return 5 + meal.cost();    }}

一个Main测试类

package decorator;public class Main{    public static void main(String[] args)    {        Meal meal = new ChineseMeal();        meal = new GreenPepperPork(meal);        meal = new HandCabbage(meal);        meal = new BraiseTenderloin(meal);        System.out.println(meal.getDescription() + "  ¥" + meal.cost());        Meal meal2 = new ChineseMeal();        meal2 = new EggplantBean(new MapoTofu(new BraiseTenderloin(meal2)));        System.out.println(meal2.getDescription() + "  ¥" + meal2.cost());    }}

运行结果

直接从eclipse复制过来

Chinese Meal, 青椒炒肉, 手撕包菜, 红烧里脊  ¥11.0Chinese Meal, 红烧里脊, 麻婆豆腐, 茄子豆角  ¥12.0

分析讨论

去食堂打菜,经济套餐,假设总共只有5种食物可供选择分别是:手撕包菜,茄子豆角,麻婆豆腐,青椒肉丝,红烧里脊。如果可以随意打菜,就可以有C15+C25+C35+C45+C55=251=31 种选择。如果写代码把这120种选择都分别弄成一个类,就有31个类。这样不仅代码重复率太高,而且如果食堂更改了上述五样菜中一样菜的价格,那么31个类的代码需要全部修改。这不符合开闭原则,不利于代码的维护和扩展。

装饰者模式就可以解决上述这种“类的爆炸式增长”问题,各种各样的排列组合太多,不能在代码中一个类一个。

装饰者模式的特点是“继承(inheritance) + 组合(Composition)”:继承是为了让component和decorator拥有相同的类型,组合是为了让所有的concreteDecorator可以“互相包装、装饰”。装饰者又名Wrapper大概就是这样来的。


Java. IO

Java.IO 中应用了装饰者模式

FileInputStream   fiStream = null;InputStreamReader iStreamReader = null;BufferedReader    bReader = null; fiStream = new FileInputStream("C:\\xxxx"); // InputStreamReader 是字节流通向字符流的桥梁、iStreamReader = new InputStreamReader(fiStream); // 从字符输入流中读取文件中的内容,装饰了一个InputStreamReader的对象bReader = new  BufferedReader(iStreamReader("C:\\xxxx"));     
一句代码版本,把3new放到一起BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\xxxx"));
1 0
原创粉丝点击