当大量不同的子类拥有固定的组件的大量不同组合时,使用继承显然会造成滥用问题。
考虑到以下两个原则:
应当将固定的组件从这些不同的组合中提取出来,用它们来修饰子类。以咖啡为例。
考虑到咖啡存在大量的种类,尤其是可以添加额外的调料,应当从咖啡的基类出发,用实例变量(布尔值)代表咖啡是否添加某种调料。
public abstract class Beverage {
private String description;
private boolean milk;
private boolean soy;
private boolean mocha;
private boolean whip;
public abstract String getDescription();
public double cost();
// getter和setter方法
// ...
}
现在只需要针对不同的咖啡种类创建子类,大大降低了需要创建的子类数量。
然而,这种方式缺乏一定的可扩展性:
分析可扩展性后,发现单纯地布尔值无法满足真实环境的需求。接下来介绍装饰者模式来解决这一问题。
装饰者模式动态地将责任与功能附加到基础对象上,提供了强大的扩展性。这就像是在使用谷歌浏览器的插件一样,用户可以使用根据自己的需求自由地组合各种功能,来实现浏览器的个性化。
装饰者模式设计一个抽象的组件基类,被修饰类和装饰类继承这个基类,而抽象的装饰类也有不同的装饰者子类,它们拥有一个组件基类的实例变量。
利用这种结构,就能不断地在基础类上扩展新的装饰者,并且基础类不需要了解其装饰者的功能与责任,这些责任与功能由装饰者自身负责。
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
public class Espresso extends Beverage { // 类似地还有其他咖啡种类
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
public class Mocha extends CondimentDecorator { // 类似地还有其他调料种类
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return 0.20 + beverage.cost();
}
}
被装饰的咖啡种类只知道自己的种类所对应的价格,最终的饮品的价格由其所有的装饰者决定。
原文:https://www.cnblogs.com/aries99c/p/12801528.html