又到了週末了,小編祝各位網友中秋快樂,闔家團圓!同時,節日期間,阿粉不打烊,歡迎網友觀看吐槽~
一、介紹
裝飾器模式,顧名思義,就是在一個類上增加功能,以起到裝飾的作用。
我們都知道,如果想給某個類新增功能,但又要避免在原類上修改程式碼,最常用的方式就是新增一個類來繼承目標類,但是如果增加多的話,會使類的數量爆炸式增長,為管理帶來巨大的麻煩,裝飾器模式就比較好地解決了這一點。
從設計的角度看,裝飾器模式涉及到四個角色:
- 被裝飾類:要進行擴充套件的源類;
- 裝飾器類:透過該類可以給被裝飾類動態新增額外的方法,多以抽象為主;
- 具體的裝飾類:該類實現自裝飾器類,已完成完整的演算法;
- 客戶角色:客戶類提出使用具體類的請求;
今天我們一起來看看深度瞭解一下裝飾器的玩法!
二、程式碼示例
下面以生產一件衣服為例,一塊布料裁剪好了之後做出的衣服樣子還可以,但是這樣的衣服是賣不出去的,因為毫無美感,因此我們需要透過一些裝飾來使衣服變得好看。
我們先來建立一個抽象類或者介面,定義一個骨架,如下:
/**
* 建立基本骨架
*/
public interface Clothes {
void makeClothes();
}
接著建立一個我們需要裝飾的源類,如下:
/**
* 被裝飾類
*/
public class MakeClothes implements Clothes {
@Override
public void makeClothes() {
System.out.println("製作一件衣服");
}
}
再來建立我們的主角,裝飾類,如下:
/**
* 裝飾類
*/
public class Decorator implements Clothes {
private Clothes clothes;
public Decorator(Clothes clothes) {
this.clothes = clothes;
}
@Override
public void makeClothes() {
clothes.makeClothes();
}
}
最後,分別建立兩個具體的裝飾類,如下:
/**
* 具體的裝飾類
*/
public class EmbroideryDecorator extends Decorator {
public EmbroideryDecorator(Clothes clothes) {
super(clothes);
}
@Override
public void makeClothes() {
super.makeClothes();
System.out.println("給衣服繡制花朵");
}
}
/**
* 具體的裝飾類
*/
public class MickeyDecorator extends Decorator {
public MickeyDecorator(Clothes clothes) {
super(clothes);
}
@Override
public void makeClothes() {
super.makeClothes();
System.out.println("給衣服繪製米老鼠圖案");
}
}
怎麼用呢?請看下面的測試類:
/**
* 客戶端
*/
public class DecorateClient {
public static void main(String[] args) {
Clothes clothes = new MakeClothes();
clothes = new EmbroideryDecorator(clothes);//給衣服繡花
clothes = new MickeyDecorator(clothes);//給衣服新增米老鼠圖案
clothes.makeClothes();
System.out.println("成品已經完成!");
}
}
輸出結果如下:
製作一件衣服
給衣服繡制花朵
給衣服繪製米老鼠圖案
成品已經完成
從結果上,可以看到,我們成功的給MakeClothes這個類,動態添加了2個方法,一個是給衣服繡花,另一個是給衣服新增米老鼠圖案,最後成品完成!
可見裝飾的效果還不錯~
三、應用
其實在 jdk 中,裝飾者設計模式也有很多典型的場景應用,例如我們熟悉的io包中的位元組輸入、輸出流,就用到了裝飾者設計模式!
其中FilterInputStream、FilterOutputStream就是裝飾類,用於動態給輸入、輸出流增加方法!
四、總結
巧妙採用裝飾器模式,可以很好的解決類繼承數量過多的問題,讓程式碼清晰可讀。
但是如果裝飾層數過多,也會影響到程式碼的維護,因此在實際的使用過程中,還需靈活使用!
原文連結:https://mp.weixin.qq.com/s/8VM5PSbByoH5jgYg1bwVgA