装饰者模式:装饰者模式是以对客户端透明的方式动态地将责任附加到对象上,已达到扩展对象功能的目的。
如果要扩展对象的功能,装饰者模式提供了比继承更有弹性的替代方案。
装饰者模式的职责:
Component
接口:装饰者和被装饰对象都要实现共同的抽象接口。ConcreteComponent
被装饰者:这是装饰者将要去装饰的真实对象,装饰者将附加责任赋予该对象。Decorator
装饰者公共的抽象类:持有被装饰对象的引用,然后在真实对象调用前后增加新的功能。ConcreteDecoratorA
:具体的装饰者对象,分别有各自功能的实现。对于煎饼,我们可以通过加蛋、加肠来装饰它!
ICake
饼接口:
/**
* 饼接口:装饰者和被装饰者都要实现这个接口
*/
public interface ICake {
/**
* 描述
*/
String description();
/**
* 价格
*/
double price();
}
Pancake
被装饰者:
/**
* 煎饼
* 被装饰者
*/
public class Pancake implements ICake {
@Override
public String description() {
return "原味煎饼";
}
@Override
public double price() {
return 5.0;
}
}
AbstractCakeDecorator
装饰者抽象父类:
/**
* 装饰者抽象父类
*/
public abstract class AbstractCakeDecorator implements ICake {
/**
* 持有被装饰者的引用
*/
private ICake pancake;
public AbstractCakeDecorator(ICake pancake) {
this.pancake = pancake;
}
public ICake getPancake() {
return pancake;
}
/**
* 由子类实现
*/
@Override
public String description() {
return "";
}
/**
* 由子类实现
*/
@Override
public double price() {
return 0;
}
}
EggPancake
装饰者1:
/**
* 加鸡蛋的煎饼
* 具体的装饰者之一
*/
public class EggPancake extends AbstractCakeDecorator {
public EggPancake(ICake pancake) {
super(pancake);
}
@Override
public String description() {
return getPancake().description() + " + 蛋";
}
@Override
public double price() {
return getPancake().price() + 2.0;
}
}
SausagePancake
装饰者2:
/**
* 加肠的煎饼
* 具体的装饰者之一
*/
public class SausagePancake extends AbstractCakeDecorator {
public SausagePancake(ICake pancake) {
super(pancake);
}
@Override
public String description() {
return getPancake().description() + " + 肠";
}
@Override
public double price() {
return getPancake().price() + 2.5;
}
}
Client
客户:
/**
* 客户
*/
public class Client {
public static void main(String[] args) {
Pancake pancake = new Pancake();
System.out.println(pancake.description());
System.out.println("总价:" + pancake.price() + " 元");
EggPancake eggPancake = new EggPancake(pancake);
System.out.println(eggPancake.description());
System.out.println("总价:" + eggPancake.price() + " 元");
SausagePancake sausagePancake = new SausagePancake(eggPancake);
System.out.println(sausagePancake.description());
System.out.println("总价:" + sausagePancake.price() + " 元");
}
}
输出:
原味煎饼
总价:5.0 元
原味煎饼 + 蛋
总价:7.0 元
原味煎饼 + 蛋 + 肠
总价:9.5 元
Process finished with exit code 0
由此可知,使用装饰者模式就不用创建大量新的类而可以拓展出具有更多功能的对象了。
IO流实现细节:
优点
(1)扩展对象功能,比继承灵活,不会导致类个数急剧增加。
(2)可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象。
(3)具体构 件 类和具体装饰类可以独立变化,用户可以根据需要自己增加新的 具体构件子类和具体装饰子类。
缺点
(1)产生很多小对象。大量小的对象占据内存,一定程度上影响性能。
(2)装饰模式易出错,调试排查比较麻烦。