一、裝飾器模式的定義
- 別名:包裝模式(Wrapper Pattern)
- 類型:結構型模式。
- 目的:指在不改變現(xiàn)有對象結構的情況下,動態(tài)地給該對象增加一些職責額外功能。
二、個人理解
給對象添加新功能時,并不是在對象類中直接添加,而是在裝飾器類中添加。
在裝飾類中添加新功能,你可以增強原先對象的方法,也可以給對象新增一個方法。
舉個抽象的例(可能并不是很貼切)
假設要給人類添加開炮功能。
但由于這是人類,咱們不能通過繼承直接給人類添加開炮功能;
所以我們就得通過組合,將機器和人類組合起來、通過變相實現(xiàn)人類可以開炮。
這個機器就是裝飾器。
- 坦克 + 人類 ,實現(xiàn)開炮功能
- 高達 + 人類 ,實現(xiàn)開炮功能
三、例子
1、菜鳥教程例子
菜鳥教程的例子都將對象和裝飾器進行了抽象處理,實現(xiàn)了可替換對象和裝飾器的實現(xiàn)類。
菜鳥教程原例子
個人覺得這樣理解裝飾器太繞了,下面的例子就只保留了對象和裝飾器。
1.1、定義對象
定義一個圓的對象
public class Circle{
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
1.2、定義裝飾器
新增setRedBorder方法去設置紅色邊框。
public class RedCircleDecorator{
private Circle c;
public RedCircleDecorator(Circle c) {
this.c = c;
}
@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Circle decoratedShape){
System.out.println("Border Color: Red");
}
}
但我覺這個菜鳥這個例子并不能把裝飾器模式特點表現(xiàn)出來。
因setRedBorder是私有,并且只是把原先draw方法進行了增強。
這樣的話,代理模式也能實現(xiàn),代理模式也能增強原有的方法,所以這里并不能把裝飾器模式特點表現(xiàn)出來。
所以我改了一下。
public class ColorCircleDecorator{
private Circle c;
public RedCircleDecorator(Circle c) {
this.c = c;
}
@Override
public void draw() {
decoratedShape.draw();
System.out.println("畫了個普通的圓");
}
public void drawRedCircle(Circle decoratedShape){
decoratedShape.draw();
System.out.println("畫了個紅色的圓");
}
public void drawBlueCircle(Circle decoratedShape){
decoratedShape.draw();
System.out.println("畫了個藍色的圓");
}
}
這個例子保留了原先的draw功能,又新增了drawRedCircle和drawBlueCircle功能。
3、JDK源碼 ——包裝類
包裝類也運用了裝飾器模式。
將基本類型 轉 包裝類 的同時,還提供各種轉換類型的功能。
4、JDK源碼 —— IO、OutputStreamWriter
OutputStreamWriter同時運用了裝飾器模式+適配器模式。
這里我們拿裝飾器部分來講。
FileOutputStream fos = new FileOutputStream(new File("Y:/學習資料.md"));
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.append("新資料xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
原本FileOutputStream 是原本沒有append功能的,
而在中OutputStreamWriter 添加append功能。
源碼:
public class OutputStreamWriter extends Writer {
private final StreamEncoder se;
public OutputStreamWriter(OutputStream out) {
super(out);
se = StreamEncoder.forOutputStreamWriter(out, lockFor(this),
out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());
}
@Override
public Writer append(CharSequence csq) throws IOException {
if (csq instanceof CharBuffer) {
se.write((CharBuffer) csq);
} else {
se.write(String.valueOf(csq));
}
return this;
}
}
可以看到雖然OutputStreamWriter 重寫了append方法。
但構造器里OutputStream又被新的裝飾器StreamEncoder接收。
而StreamEncoder類就已經通過繼承Writer 增加了append方法。
public final class StreamEncoder extends Writer {
private final OutputStream out;
private StreamEncoder(OutputStream out, Object lock, CharsetEncoder enc) {
super(lock);
this.out = out;
this.ch = null;
this.cs = enc.charset();
this.encoder = enc;
this.bb = ByteBuffer.allocate(INITIAL_BYTE_BUFFER_CAPACITY);
this.maxBufferCapacity = MAX_BYTE_BUFFER_CAPACITY;
}
public static StreamEncoder forOutputStreamWriter(OutputStream out, Object lock, Charset cs) {
return new StreamEncoder(out, lock, cs);
}
}
5、Spring源碼 —— BeanWrapperImpl
BeanWrapperImpl類是對BeanWrapper接口的默認實現(xiàn),它包裝了一個bean對象,緩存了bean的內省結果,并可以訪問bean的屬性、設置bean的屬性值。
BeanWrapperImpl功能還挺復雜的,大家可以自行去看源碼,我就不貼出來了。
5、SpringMVC源碼 —— HttpHeadResponseDecorator
HttpHeadResponseDecorator 給ServerHttpResponse 添加了writeWith、writeAndFlushWith的功能。
public class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {
public HttpHeadResponseDecorator(ServerHttpResponse delegate) {
super(delegate);
}
public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
return this.shouldSetContentLength() && body instanceof Mono ? ((Mono)body).doOnSuccess((buffer) -> {
if (buffer != null) {
this.getHeaders().setContentLength((long)buffer.readableByteCount());
DataBufferUtils.release(buffer);
} else {
this.getHeaders().setContentLength(0L);
}
}).then() : Flux.from(body).doOnNext(DataBufferUtils::release).then();
}
private boolean shouldSetContentLength() {
return this.getHeaders().getFirst("Content-Length") == null && this.getHeaders().getFirst("Transfer-Encoding") == null;
}
public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
return this.setComplete();
}
}
四、其他設計模式
創(chuàng)建型模式
結構型模式文章來源:http://www.zghlxwxcb.cn/news/detail-737675.html
- 1、設計模式——裝飾器模式(Decorator Pattern)+ Spring相關源碼
行為型模式文章來源地址http://www.zghlxwxcb.cn/news/detail-737675.html
- 1、設計模式——訪問者模式(Visitor Pattern)+ Spring相關源碼
- 2、設計模式——中介者模式(Mediator Pattern)+ JDK相關源碼
- 3、設計模式——策略模式(Strategy Pattern)+ Spring相關源碼
- 4、設計模式——狀態(tài)模式(State Pattern)
- 5、設計模式——命令模式(Command Pattern)+ Spring相關源碼
- 6、設計模式——觀察者模式(Observer Pattern)+ Spring相關源碼
- 7、設計模式——備忘錄模式(Memento Pattern)
- 8、設計模式——模板方法模式(Template Pattern)+ Spring相關源碼
- 9、設計模式——迭代器模式(Iterator Pattern)+ Spring相關源碼
- 10、設計模式——責任鏈模式(Chain of Responsibility Pattern)+ Spring相關源碼
- 11、設計模式——解釋器模式(Interpreter Pattern)+ Spring相關源碼
到了這里,關于設計模式——裝飾器模式(Decorator Pattern)+ Spring相關源碼的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!