裝飾者模式
- 裝飾者模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作爲現有的類的一個包裝。
- 這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
- 我們通過下面的實例來演示裝飾者模式的用法
注意
要實現裝飾者模式,注意以下幾點內容:
a.裝飾者類要實現真實類同樣的接口
b.裝飾者類內有一個真實對象的引用(可以通過裝飾者類的構造器傳入)
c.裝飾者類對象在主類中接受請求,將請求發給真實的對象(相當於已經將引用傳遞到了裝飾類的真實對象)
d.裝飾者可以在傳入真實對象後,增加一些附加功能(因爲裝飾對象和真實對象都有同樣的方法,裝飾對象可以添加一定的操作在調用真實對象的方法,或者先調用真實對象的方法,再添加自己的方法)
e.不用繼承
示例
- 生產饅頭的示例
- 假設要製造添加糖和玉米麪的饅頭:
- 需要一個正常的饅頭
- 添加玉米麪和糖
- 和麪,最後生產出饅頭
- 饅頭接口
package waking.test.zs;
public interface IBread {
void prepare();
void kneadFlour();
void steamed();
void process();
}
package waking.test.zs;
public class NormaIBread implements IBread {
@Override
public void prepare() {
System.out.println("開始準備工作、、、、");
}
@Override
public void kneadFlour() {
System.out.println("開始和麪、、、、、");
}
@Override
public void steamed() {
System.out.println("開始蒸饅頭、、、、");
}
@Override
public void process() {
prepare();
kneadFlour();
steamed();
}
}
package waking.test.zs;
public abstract class AbstIBread implements IBread{
private final IBread iBread;
public AbstIBread(IBread iBread) {
super();
this.iBread = iBread;
}
@Override
public void prepare() {
this.iBread.prepare();
}
@Override
public void kneadFlour() {
this.iBread.kneadFlour();
}
@Override
public void steamed() {
this.iBread.steamed();
}
@Override
public void process() {
prepare();
kneadFlour();
steamed();
}
}
package waking.test.zs;
public class SweetDecorator extends AbstIBread{
public SweetDecorator(IBread iBread) {
super(iBread);
}
public void sweet() {
System.out.println("加點糖、、、、");
}
@Override
public void kneadFlour() {
this.sweet();
super.kneadFlour();
}
}
package waking.test.zs;
public class CornDecorator extends AbstIBread {
public CornDecorator(IBread iBread) {
super(iBread);
}
public void addCorn() {
System.out.println("添加玉米、、、");
}
@Override
public void kneadFlour() {
this.addCorn();
super.kneadFlour();
}
}
package waking.test.zs;
import org.junit.Test;
public class Tests {
@Test
public void Test1() {
System.out.println("開始裝飾饅頭、、、");
IBread iBread = new NormaIBread();
iBread = new SweetDecorator(iBread);
iBread = new CornDecorator(iBread);
iBread.process();
System.out.println("裝飾完畢");
}
}
開始裝飾饅頭、、、
開始準備工作、、、、
添加玉米、、、
加點糖、、、、
開始和麪、、、、、
開始蒸饅頭、、、、
裝飾完畢
總結
- 意圖:動態的給一個對象添加一些額外的職責。就增加功能來說,裝飾者模式相比子類更靈活
- 主要解決:一般的,我們爲了擴展一個類經常使用繼承方式實現,由於繼承爲類引入靜態特徵,並且隨着擴展功能的增多,子類會很膨脹
- 優點:裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能
- 缺點:多層修飾比較複雜
- 使用場景:
- 注意事項:可以替代繼承