裝飾者的應用
所謂裝飾者,說白了,目的就是對現有的物件進行增強,裝飾者設計模式最大的優點就是,它在擴充套件類原有功能的基礎上還避免的類爆炸的情況
Netty中的裝飾者模式的應用
ByteBuf
是netty中重要的資料容器類,我們看它是如何設計的,如下圖
我們可以看到,ByteBuf
的直接實現類有五個,忽略WrappedByteBuf
這個類,其實直接實現類有四個,為什麼要忽略掉WrappedByteBuf
呢? 因為是它是ByteBuf
裝飾者的基類; 它本身沒有任何實現任何功能;
netty的設計者在設計ByteBuf
的繼承體系時,發現上圖中的四個直接實現類可能都需要新增新的功能,這倆功能是
- 不可釋放的功能
- 簡單的洩漏感知的功能
怎麼擴充套件這個功能呢?
如果選擇繼承的話,現有的四個類全部多出兩個子類,讓子類新增上特定的功能, 雖然解決了問題,但是類的數量出現了爆炸式的增長 從原來的4長到了 4+4*2
看上面的圖,其實netty的設計者選擇的處理模式是裝飾者模式,只新增了三個類,就達到了同樣的效果
裝飾者的設計套路
- 新增一個裝飾者頂級類,這個類和需要裝飾的元件類在繼承處於相等的地位
- 這個裝飾者類並不作任何的構工作,維護著
ByteBuf
的引用, 重寫的ByteBuf
的所有方法都是用這個引用完成具體的功能
- 這個裝飾者類並不作任何的構工作,維護著
原始碼如下:
*/
class WrappedByteBuf extends ByteBuf {
protected final ByteBuf buf;
protected WrappedByteBuf(ByteBuf buf) {
if (buf == null) {
throw new NullPointerException("buf");
}
this.buf = buf;
}
@Override
public final boolean hasMemoryAddress() {
return buf.hasMemoryAddress();
}
@Override
public final long memoryAddress() {
return buf.memoryAddress();
}
...
- 具體的裝飾者,繼承上面的裝飾者的頂級類, 在自己的建構函式中接收
ByteBuf
的型別的引數,並把它傳遞給它的父類,使用者在裝飾者時,會把建立的最上面的四種待裝飾的元件類以構造方法的形式傳遞進去,整個體系就執行起來了, 而且裝飾者可以按照自己的需求重寫父類的方法, 或者在現在的基礎上新增新的方法呼叫進行增強
原始碼如下
*/
final class UnreleasableByteBuf extends WrappedByteBuf {
private SwappedByteBuf swappedBuf;
UnreleasableByteBuf(ByteBuf buf) {
super(buf instanceof UnreleasableByteBuf ? buf.unwrap() : buf);
}
@Override
public ByteBuf order(ByteOrder endianness) {
if (endianness == null) {
throw new NullPointerException("endianness");
}
if (endianness == order()) {
return this;
}
SwappedByteBuf swappedBuf = this.swappedBuf;
if (swappedBuf == null) {
this.swappedBuf = swappedBuf = new SwappedByteBuf(this);
}
return swappedBuf;
}
@Override
public ByteBuf asReadOnly() {
return buf.isReadOnly() ? this : new UnreleasableByteBuf(buf.asReadOnly());
}
...