设计模式之(三)——装饰者模式(Decorator Pattern)
程序员文章站
2022-07-13 22:05:45
...
装饰者模式:动态将责任附加到对象上,要拓展功能,提供了比继承更有弹性的方案。
很多文章也是拿了书上的例子来讲,同时写到,有的调料装饰者都必须实现 getDescription() 大家可以先考虑下,稍后我们会说。最后都是没说,还有思考的同时你也应该会抛出一些问题,这样能让你对该模式的印象更加的深刻。
/**
* 饮料
*/
public abstract class Beverage {
public String description = "unknown";
public String getDescription(){
return description;
}
public abstract double cost();
}
/**
* 装饰者
*/
public abstract class Condiment extends Beverage{
@Override
public abstract String getDescription();
}
/**
* 浓咖啡,被装饰者
*/
public class Latte extends Beverage{
@Override
public String getDescription() {
return "Latte";
}
@Override
public double cost() {
return 1.0;
}
}
/**
* 具体的装饰者
*/
public class Milk extends Condiment {
public Beverage beverage;
public double milkcost = 0.5;
public Milk(Beverage beverage){
this. beverage = beverage;
}
@Override
public String getDescription () {
return "milk add:"+ beverage.getDescription();
}
@Override
public double cost () {
return milkcost+ beverage.cost();
}
}
/**
* 具体装饰者
*/
public class Whip extends Beverage {
public Beverage beverage;
public double whipcost = 0.2;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return "whip add:" + beverage.getDescription();
}
@Override
public double cost () {
return whipcost+ beverage.cost();
}
public class TestA {
public static void main(String[] args) {
Beverage b = new Espresso();
Condiment c = new Milk(b);
System. out.println(c.getDescription());
System. out.println(c.cost());
}
}
public class TestB {
public static void main(String[] args) {
Beverage b = new Espresso();
System. out.println(b.cost()+ " "+b.getDescription());
Beverage c = new Milk(b); //第一个装饰,把装饰者当成了构造器参数
c = new Milk(c);//第二个装饰
c = new Whip(c);//第三个装饰
System. out.println(c.cost()+ " "+c.getDescription());
}
}
TestA只是很简单的一层装饰,TestB才是装饰者的核心所在。
这样能一层嵌一层。这才是核心。但是没搞懂,为什么装饰器,实现的是Condiment。
而Condiment本身就是继承Beverage。我的Milk和Whip直接继承Beverage也是可以的。
为什么装饰者都去先继承了Decorator,问过有经验的人,给了我很生动的比喻,具体的装饰者就是稀饭,炒饭,干饭,中间层是饭。再结合自己所思考的,如果饭继承是食物,那么你用稀饭直接去继承食物也是没问题的。中间层是给了一层清晰的分类。专门用来区分装饰者。你看Milk和Whip的继承就明显看出这两者是装饰者。所以中间层的目的在此,是对所有装饰者集合的一层抽象,暂时想到的是这些。
由IO流的使用你就可以发现模式的缺点,装饰者的设计会导致有很多很多类,使用api的时候不清晰。但是可以通过对象之前的嵌入组合扩展出很多行为,这也是装饰者模式最大的优点。
下一篇: Unity截图的几种方式