观察者模式定义:
区别于继承的用于增强对象功能的动态可扩展的设计模式。
什么时候可以使用观察者模式?
举个栗子,现在咖啡厅想要对外提供几种饮品,黑咖啡和浓咖啡,另外i还会提供一些调料。这时候他们需要计算出不同组合的饮品和调料的价格是多少。
面对这种问题,我们可能会用常用的继承思想来进行实现,首先定义一个饮料基类,拥有抽象cost方法来计算总费用,定义调料的设置和获取方法,再定义不同的子类实体继承基类,设置不同的调料。
这样做的缺点:
1:一旦出现新的调料,我们就必须修改基类中的调料的种类,新增新的方法
2:会出现新的饮料比如说茶,而饮料基类中的摩卡和奶泡调料就不适合新的饮料类型
3:如果调料价格有所改变,就必须改变基类中的调料的价格
以上的几种做法违背了开闭原则,扩展性不够,而装饰者模式则提供给我们另一种方式去增强类的功能,符合开闭原则,而且拥有较好的扩展性,区别于常用的继承。
以下是装饰者模式的具体代码示例:
//饮料抽象类
public abstract class Beverage {
String description = "Unkown Beverage";
public String getDescription(){
return description;
}
public abstract double cost();
}
//调料抽象类
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
//浓咖啡
public class Espresso extends Beverage {
public Espresso(){
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
//摩卡
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Mocha";
}
@Override
public double cost() {
return 0.20 + beverage.cost();
}
}
//奶泡
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Whip";
}
@Override
public double cost() {
return 0.30 + beverage.cost();
}
}
//装饰者模式测试类
public class StarbuzzCoffeeTest {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()+"$"+beverage.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Whip(beverage2);
beverage2 = new Mocha(beverage2);
System.out.println(beverage2.getDescription()+"$"+beverage2.cost());
}
}
首先定义出饮料抽象类基类Beverage,在其中定义描述方法和抽象cost方法,继承饮料抽象基类实现一个浓咖啡子类,定义调料抽象类继承饮料基类,再根据调料抽象类实现两个调料子类,最后在测试类中实例化黑咖啡实例,通过实例化不同的调料子类来获得功能增强后的黑咖啡,最后输出调制出黑咖啡所需的材料和花费。
如果大家有看过我之前写的代理模式,可能会发现,代理模式和装饰者模式有些类似的地方,它们都动态的增加了类的行为,但是他们的主要目的又是不同的,代理模式为目标类生成了代理类,调用者通过调用代理类来调用达到对目标类控制和隐藏的效果,主要是为了控制目标类,而装饰者模式的主要目的是为了扩展功能。
如果有哪里说的不对的地方,还请大家指出来。