裝飾着模式(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句柄,所以沒法使用我們在抽象裝飾者裏創建的抽象方法,這種叫半透明裝飾模式,我們需要使用雞蛋裝飾者等具體裝飾者作爲句柄才能使用特有接口。真正的裝飾者模式指透明裝飾者模式。
透明裝飾者模式:在透明裝飾模式中,要求客戶端完全針對抽象編程,裝飾模式的透明性要求客戶端程序不應該將對象聲明爲具體構件類型或具體裝飾類型,而應該全部聲明爲抽象構件類型。