装饰着模式(Decorator Partten):是一种对象结构模式,动态地给一个对象添加额外的职责,增加功能来说,装饰者比生成子类实现更加灵活。
装饰者模式又叫包装模式,通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案。
为了让系统具有更好的灵活性和可扩展性,我们通常会定义一个抽象装饰类,而将具体的装饰类作为他的子类。
装饰模式的核心在于抽象装饰类的设计。.
下面是一个生产煎饼的例子,可以买煎饼、煎饼加蛋、煎饼加火腿、煎饼加蛋加火腿等等。加蛋和加火腿在这里是装饰者。
抽象的产品类ABetterCake提供了描述和价格的接口。具体的实现类BetterCake描述产品是煎饼,价格是8块:
/**
* 具体构件
*/
public class BetterCake extends ABetterCake {
@Override
protected String getDesc() {
return "煎饼";
}
@Override
protected int cost() {
return 8;
}
}
抽象的装饰者AbstractDecorator中对实现类BetterCake煎饼进行了组合并简单包装了煎饼类的方法
/**
* 抽象装饰者
*/
public abstract class AbstractDecorator extends ABetterCake{
private ABetterCake aBetterCake;
public AbstractDecorator(ABetterCake aBetterCake) {
this.aBetterCake = aBetterCake;
}
//抽象装置者自定义的方法
protected abstract void doSomething();
@Override
protected String getDesc() {
return this.aBetterCake.getDesc();
}
@Override
protected int cost() {
return this.aBetterCake.cost();
}
}
加蛋哥出现!
/**
* 具体装饰者——鸡蛋装饰器 加一个蛋
*/
public class EggDecorator extends AbstractDecorator {
public EggDecorator(ABetterCake aBetterCake) {
super(aBetterCake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc()+"加一个鸡蛋";
}
@Override
protected int cost() {
return super.cost()+1;//加一块钱
}
public void egg() {
System.out.println("加一个鸡蛋");
}
}
加肠哥出现!
/**
* 香肠装饰类
*/
public class SausageDecorator extends AbstractDecorator {
public SausageDecorator(ABetterCake aBetterCake) {
super(aBetterCake);
}
@Override
protected void doSomething() {
}
@Override
protected String getDesc() {
return super.getDesc() + "加一个肠";
}
@Override
protected int cost() {
return super.cost() + 2;
}//一个肠为啥两块???
}
开卖!
/**
* 测试类
*/
public class Main {
public static void main(String[] args) {
ABetterCake aBetterCake = new BetterCake();
System.out.println("老板,买一个"+aBetterCake.getDesc()+",花费:"+aBetterCake.cost());
aBetterCake = new EggDecorator(aBetterCake);
System.out.println("老板,买一个"+aBetterCake.getDesc()+",花费:"+aBetterCake.cost());
aBetterCake = new SausageDecorator(aBetterCake);
System.out.println("老板,买一个"+aBetterCake.getDesc()+",花费:"+aBetterCake.cost());
System.out.println("-----------------------");
ABetterCake aBetterCake1 = new BetterCake();//新煎饼
aBetterCake1 = new EggDecorator(aBetterCake1);//加一个蛋
aBetterCake1 = new EggDecorator(aBetterCake1);//再加一个蛋
System.out.println("老板,买一个"+aBetterCake1.getDesc()+",花费:"+aBetterCake1.cost());
}
}
结果:
老板还有话要说:上面这种销售方式全使用aBetterCake句柄,所以没法使用我们在抽象装饰者里创建的抽象方法,这种叫半透明装饰模式,我们需要使用鸡蛋装饰者等具体装饰者作为句柄才能使用特有接口。真正的装饰者模式指透明装饰者模式。
透明装饰者模式:在透明装饰模式中,要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该将对象声明为具体构件类型或具体装饰类型,而应该全部声明为抽象构件类型。