說到裝飾裁僧,我們首先能想到的是房間中的各種陳設(shè)和布景铺坞。在房間中惯悠,每增加一個裝飾物品,整個房間的氛圍都會有所改變遮斥。而我們的裝飾者模式也起到了這么一個作用:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
動態(tài)地為一個對象增加其他功能峦失。裝飾者模式提供了一種靈活的方案來替代子類的繼承。
我們來看一下裝飾者模式的框架:
- Component: 即是我們需要裝飾的對象伏伐,Component是抽象的宠进,定義了該對象的方法。實(shí)際上我們要裝飾的不是這個對象藐翎,而是這個對象的方法材蹬,在方法被調(diào)用前或后增加其他邏輯,或?qū)崿F(xiàn)其他效果吝镣;
- ConcreteComponent: 即是上述對象子類化后的類堤器,實(shí)現(xiàn)了抽象方法;
- Decorator: 裝飾者末贾,也繼承了Component類闸溃,同樣需要定義相同的方法;
- ConcreteDecoratorA & B: 具體的裝飾者類拱撵,覆蓋了Component的方法辉川,增加了裝飾邏輯;
其實(shí)說白了拴测,就是使用合理的覆蓋來實(shí)現(xiàn)多層次的方法疊加乓旗,達(dá)到裝飾原始內(nèi)部方法的效果。
我們來看一個例子集索,使用裝飾者模式屿愚,將一個普通的文字裝飾成斜體(Italic)+粗體(Bold)的字體。
Component
我們首先定義需要進(jìn)行裝飾的抽象類务荆,它是一個文本妆距,定義了獲得文本字體的方法getFont()
。
public abstract class MockText {
public abstract Font getFont();
}
ConcreteComponent
然后我們需要一個實(shí)現(xiàn)類來繼承MockText:
ublic class ConcreteText extends MockText {
private Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
@Override
public Font getFont() {
return font;
}
Decorator
而后我們需要一個抽象的裝飾者函匕,這個裝飾者需要繼承Component以獲得同樣的行為娱据。它使用一個MockText作為構(gòu)造函數(shù)的參數(shù):
public abstract class FontDecorator extends MockText {
private MockText text;
public FontDecorator(MockText text) {
this.text = text;
}
@Override
public Font getFont() {
return text.getFont();
}
}
ConcreteDecorator
而后我們需要兩個具體的Decorator實(shí)現(xiàn)類,用來將字體變?yōu)樾斌w和粗體:
public class BoldTextDecorator extends FontDecorator {
public BoldTextDecorator(MockText text) {
super(text);
}
@Override
public Font getFont(){
Font font = super.getFont();
return new Font(font.getName(), font.getStyle() | Font.BOLD,font.getSize());
}
}
public class ItalicTextDecorator extends FontDecorator{
public ItalicTextDecorator(MockText text) {
super(text);
}
@Override
public Font getFont(){
Font font = super.getFont();
return new Font(font.getName(), font.getStyle() | Font.ITALIC,font.getSize());
}
}
最后我們使用一個main函數(shù)來驅(qū)動這個框架:
public static void main(String[] args){
MockText text= new ConcreteText();
System.out.println(text.getFont());
text = new BoldTextDecorator(text);
text = new ItalicTextDecorator(text);
System.out.println(text.getFont());
}
我們嘗試打印了兩次text.getFont的結(jié)果盅惜,結(jié)果如下:
java.awt.Font[family=SansSerif,name=SansSerif,style=plain,size=12]
java.awt.Font[family=SansSerif,name=SansSerif,style=bolditalic,size=12]
可以看到第一次的style還是plain中剩,而第二次的style已經(jīng)變成了bolditalic