【設計模式】設計模式真的懂得這些就夠了,來來來,從代理模式&裝飾器模式講起......

設計模式分爲三種:
1. 創建型
工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
2. 結構型
適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
3. 行爲型
策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

本篇Colin帶你從『結構型』設計模式中的『代理模式』和『裝飾器模式』。

一. 代理模式

1. 從UML圖中理解『代理模式』中類的結構關係

這裏寫圖片描述
代理模式的類結構非常簡單,其主要成員有一個接口、一個實現了該接口的實現類、一個代理類。代理模式的定義是,給某一個對象提供一個代理對象,並由代理對象控制對原對象的引用。顧名思義,代理模式就是提供了一箇中介,來爲原對象完成某項任務。


舉個栗子:攜程app的圖片加載框架有兩種,一種是universalImageLoader,一種是fresco,那麼業務部門要想使用圖片加載器時,他們是直接調用universalImageLoader/fresco的接口嗎?如果是這樣,那哪天框架組宣佈停用其中一種圖片加載框架,或是新增Glide圖片加載框架時,業務部門的代碼是不是就要重新全部重新寫?這個時候就可以使用代理模式提供一箇中介,中介可以控制使用哪種圖片加載框架,業務部門也只是調用中介提供的方法,而不用管具體實現是哪種圖片加載框架。

2. 爲什麼要用『代理模式』?

  • 中介隔離作用:在某些情況下,一個客戶類不想或者不能直接引用一個委託對象,而代理類對象可以在客戶類和委託對象之間起到中介的作用,其特徵是代理類和委託類實現相同的接口。
  • 開閉原則,增加功能:代理類除了是客戶類和委託類的中介之外,我們還可以通過給代理類增加額外的功能來擴展委託類的功能,這樣做我們只需要修改代理類而不需要再修改委託類,符合代碼設計的開閉原則。代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及事後對返回結果的處理等。代理類本身並不真正實現服務,而是同過調用委託類的相關方法,來提供特定的服務。真正的業務功能還是由委託類來實現,但是可以在業務功能執行的前後加入一些公共的服務。例如我們想給項目加入緩存、日誌這些功能,我們就可以使用代理類來完成,而沒必要打開已經封裝好的委託類。

3. 一言不合上代碼

一個接口

 public interface ImageLoader {
     void display();
 }

一個接口實現類

 public class FrescoImageLoader implements ImageLoader { 
     @Override
     public void display() {
         System.out.println("fresco加載圖片");
     }
 }

一個代理

public class ImageLoaderHelper implements ImageLoader {
     private ImageLoader imageLoader; 
     public ImageLoaderHelper(final ImageLoader imageLoader) {
         this.imageLoader = imageLoader;
     }
     @Override
     public void display() {
         imageLoader.display();
     }
 }

二. 裝飾模式

1. 從UML圖中理解『裝飾模式』中類的結構關係

這裏寫圖片描述
裝飾模式的類結構也非常簡單,包括一個接口、一個接口的實現類、一個抽象裝飾類、多個具體裝飾類。裝飾模式的定義是,動態地給一個對象增加一些額外的職責,就增加對象功能來說,裝飾模式比「子類繼承父類」實現更爲靈活。


舉個栗子:我們喝一杯咖啡,可以加奶、加糖、加冰塊。有的人喜歡喝加糖的咖啡,有的人喜歡喝加奶的咖啡,還有的人喜歡喝加冰塊的咖啡。當然,我們也可以採用繼承的方式喝到我們想喝的咖啡,不過接下來我們看看採用組合的方式如何實現。

2. 爲什麼要用『裝飾模式』?

  • 裝飾類和被裝飾類可以獨立發展,不會相互耦合
  • 動態的將責任附加到對象身上。

3. 一言不合上代碼

一個接口

public interface Drink {
    public void taste();
}

一個接口實現類

public class Coffee implements Drink {
    public float taste() {
        System.out.println("咖啡好苦,好提神");
    }
}

一個抽象裝飾類

public abstract class Decorator implements Drink {
    protected Drink decorator;

    public CondimentDecorator(Drink decorator) {
        this.decorator = decorator;
    }

    public void taste() {
        decorator.taste()
    }
}

加糖

public class Sugar extends Decorator {
    public Sugar(Drink decorator) {
        super(decorator);
    }

    @Override
    public void taste() {
        System.out.println("加了糖,味道甜多了");
    }
}

加奶

public class Milk extends Decorator {
    public Milk(Drink decorator) {
        super(decorator);
    }

    @Override
    public void taste() {
        System.out.println("加了奶,味道綿綢多了");
    }
}

加冰

public class Ice extends Decorator {
    public Ice(Drink decorator) {
        super(decorator);
    }

    @Override
    public void taste() {
        System.out.println("加了冰,好涼爽");
    }
}

三. 裝飾模式和代理模式不是一樣嗎??

代理模式和裝飾模式非常類似,甚至代碼都類似。二者最主要的區別是:代理模式中,代理類對被代理的對象有控制權,決定其執行或者不執行,主要是隔離了真正實現。而裝飾模式中,裝飾類對代理對象沒有控制權,只能爲其增加一層裝飾,以加強被裝飾對象的功能,僅此而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章