裝飾模式(Decorator Pattern)能動態(tài)附加對象的功能,裝飾器提供了比繼承更為靈活的擴(kuò)展方案。
這個(gè)模式是繼承的一種代替方案。
一般而言,這個(gè)模式的底層是一個(gè)接口或者是抽象類。然后還需要裝飾類來擴(kuò)展該接口或者繼承抽象類,并進(jìn)行“聚合”操作。也就是說,裝飾類是在原有的功能上附加額外的功能。
還是來看代碼吧:
Troll接口,意思是怪物?巨魔?有三個(gè)函數(shù)。
/**
*
* Interface for trolls
*
*/
public interface Troll {
void attack();
int getAttackPower();
void fleeBattle();
}
然后SimpleTroll類,使用Troll接口。
/**
*
* SimpleTroll implements {@link Troll} interface directly.
*
*/
public class SimpleTroll implements Troll {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTroll.class);
@Override
public void attack() {
LOGGER.info("The troll tries to grab you!");
}
@Override
public int getAttackPower() {
return 10;
}
@Override
public void fleeBattle() {
LOGGER.info("The troll shrieks in horror and runs away!");
}
}
裝飾類TrollDecorator,可以看到,它不僅是使用了Troll接口,自己還另外帶一個(gè),并把接口函數(shù)全都委托給另帶的那個(gè)。
/**
* TrollDecorator is a decorator for {@link Troll} objects. The calls to the {@link Troll} interface
* are intercepted and decorated. Finally the calls are delegated to the decorated {@link Troll}
* object.
*
*/
public class TrollDecorator implements Troll {
private Troll decorated;
public TrollDecorator(Troll decorated) {
this.decorated = decorated;
}
@Override
public void attack() {
decorated.attack();
}
@Override
public int getAttackPower() {
return decorated.getAttackPower();
}
@Override
public void fleeBattle() {
decorated.fleeBattle();
}
}
一個(gè)具體的裝飾實(shí)現(xiàn),繼承裝飾類,調(diào)用超類的基礎(chǔ)上再自己加入一些東西,而超類的實(shí)現(xiàn)也就是外帶的Troll接口實(shí)現(xiàn),這樣就在原有Troll之外增加了功能。
/**
* Decorator that adds a club for the troll
*/
public class ClubbedTroll extends TrollDecorator {
private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class);
public ClubbedTroll(Troll decorated) {
super(decorated);
}
@Override
public void attack() {
super.attack();
LOGGER.info("The troll swings at you with a club!");
}
@Override
public int getAttackPower() {
return super.getAttackPower() + 10;
}
}
你也許會問:這不還是繼承嗎?確實(shí)用到了繼承,但和單純使用繼承來擴(kuò)展功能還是有很大區(qū)別的。區(qū)別是什么呢?就是運(yùn)行時(shí)可以改變類的行為。
public static void main(String[] args) {
// simple troll
LOGGER.info("A simple looking troll approaches.");
Troll troll = new SimpleTroll();
troll.attack();
troll.fleeBattle();
LOGGER.info("Simple troll power {}.\n", troll.getAttackPower());
// change the behavior of the simple troll by adding a decorator
LOGGER.info("A troll with huge club surprises you.");
Troll clubbed = new ClubbedTroll(troll);
clubbed.attack();
clubbed.fleeBattle();
LOGGER.info("Clubbed troll power {}.\n", clubbed.getAttackPower());
}
}
SimpleTroll就是普通的一個(gè)Troll,給它套上ClubbedTroll裝飾,馬上就有了ClubbedTroll的功能。以此類推,還可以加別的裝飾。這又是和繼承的另一個(gè)重要的區(qū)別:自由組合。
N個(gè)裝飾者總共可以產(chǎn)生2^N個(gè)不同類,如果一個(gè)個(gè)繼承的話……
當(dāng)然,由于裝飾者的特性,最好額外功能不要求特定的順序,也就是說額外功能之間互不影響為最佳。