聊一聊設計模式(三)-- 結構型設計模式

前言

憋在家裏的第8天,今天開始進入結構型設計模式。java

思惟導圖

結構型設計模式是從程序的結構上解決模塊之間的耦合問題。設計模式

代理模式

定義:爲其餘對象提供一種代理以控制對這個對象的訪問。安全

這個模式的幾個角色分爲如下:ide

  1. Subject:抽象主題類。
  2. RealSubject:真實主題類,客戶端由Proxy來間接調用。
  3. Proxy:代理類

這個模式就像你和代購的存在同樣,你提出需求,由代購來幫你購買。這個句子裏基本上就歸納了整個代理模式的全貌。客戶端就是咱們需求者,而真實主題就是你要找的代購幫你買,最後一個代理,找誰買。 如下用代碼表示靜態代理。post

/** * 抽象主題類 * 中心主題,買東西。 */
public interface Shop {
    void buy();
}

/** * 真實主題類 * 有這麼一我的,能夠幹這件事,他就是代理 */
public class Person implements Shop {
    @Override
    public void buy() {
        System.out.println("購買");
    }
}

/** * 代理類 * 你要告訴本身找那個代購買 */
public class WhoBuy implements Shop {
    private Shop shop;

    WhoBuy(Shop shop){
        this.shop = shop;
    }
    @Override
    public void buy() {
        shop.buy();
    }
}

/** * 客戶端類 * 就是這個想買東西的人了 */
public class User {
    public static void main(String[] args) {
        Shop person = new Person();
        Shop purchase = new WhoBuy(person);
        purchase.buy();
    }
}
複製代碼

靜態代理,主要是爲了讓人更好的理解代理模式。在開發中主要仍是使用反射機制來完成的,也就是動態代理模式。學習

/** * 動態代理類 */
public class DynamicPurchase implements InvocationHandler {
    private Object object;
    DynamicPurchase(Object object){
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        if(method.getName().equals("buy")){
            System.out.println("買上");
        }
        return result;
    }
}

/** * 客戶端類 */
public class User {
    public static void main(String[] args) {
        Shop person = new Person();
        DynamicPurchase dynamicPurchase = new DynamicPurchase(person);
        ClassLoader loader = person.getClass().getClassLoader();
        Shop purchase = (Shop) Proxy.newProxyInstance(loader, new Class[]{Shop.class}, dynamicPurchase);
        purchase.buy();
    }
}
複製代碼

和靜態代理的不一樣就在於代理類,使用反射機制。 這種代理模式的優勢:this

  1. 真實主題類只關注自己的業務邏輯。
  2. 真實主題類和代理類實現了公共接口,沒必要擔憂主題類的修改影響代理類。

裝飾模式

動態地給一個對象添加一些額外的職責。spa

這個模式的角色有:設計

  1. Component:抽象組件。
  2. ConcreteComponent:組件具體實現類。
  3. Decorator:抽象裝飾者,用於增長Component類的功能。
  4. ConcreteDecorator:裝飾者的具體實現

人是一個慢慢學習的生物,從一開始只會咿咿呀呀,通過學習,學會了數學,英語。這個時候數學、英語,兩個科目就是一種裝飾了。代理

/** * 抽象組件 * 做爲一我的,必然會有學習的能力。 */
public abstract class Person {
    public abstract void learn();
}

/** * 組件具體實現類 * 人一開始只會咿咿呀呀 */
public class Me extends Person {
    @Override
    public void learn() {
        System.out.println("咿咿呀呀");
    }
}

/** * 抽象裝飾類 * 有一個老師教書育人 */
public abstract class Teacher extends Person {
    
    private Person person;
    
    Teacher(Person person){
        this.person = person;
    }    
    @Override
    public void learn() {
        person.learn();
    }
}

/** * 裝飾具體類 * 這個老師教數學,也就教會了孩子 */
public class MathTeacher extends Teacher {
    MathTeacher(Person person) {
        super(person);
    }

    public void teach(){
        System.out.println("學會了數學");
    }

    @Override
    public void learn() {
        super.learn();
        teach();
    }
}

// 具體使用
public class Main {
    public static void main(String[] args) {
        Person person = new Me();
        MathTeacher mathTeacher = new MathTeacher(person);
        mathTeacher.learn();
    }
}
複製代碼

優勢:

  1. 可以動態的爲對象增長功能。
  2. 裝飾類和組件類互不干擾。 缺點:
  3. 不管是裝飾類,仍是組件類都繼承自Component,若是Component發生了改變,子類必然收到巨大的衝擊。
  4. 裝飾層數不宜過多,不只影響效率,排查也比較苦難。

外觀模式

要求一個子系統 的外部與內部的通訊必須經過一個統一的對象進行。

這個模式的角色有:

  1. Facade:外觀類
  2. Subsystem:子系統類

這裏以爲以前看到的武俠的例子很是好。 一個武俠自己分爲招式、內功、經脈三個系統,每次放招都是根據三個子系統的合理使用來釋放。

/** * 三大子系統 */
public class 經脈 {
    public void jingmai(){
        System.out.println("開啓經脈");
    }
}

public class 內功 {
    public void JiuYang(){
        System.out.println("使用九陽神功");
    }

    public void QianKun(){
        System.out.println("使用乾坤大挪移");
    }
}

public class 招式 {
    public void QiShangQuan(){
        System.out.println("使用七傷拳");
    }

    public void ShengHuoLing(){
        System.out.println("使用聖火令");
    }
}

/** * 外觀類 * 也就是張無忌 */
public class 張無忌 {
    private JingMai jingMai;
    private NeiGong neiGong;
    private ZhaoShi zhaoShi;
    
    張無忌(){
        jingMai = new JingMai();
        neiGong = new NeiGong();
        zhaoShi = new ZhaoShi();
    }
    
    public void QianKun(){
        jingMai.jingmai();
        neiGong.QianKun();
    }
    
    public void QiShang(){
        jingMai.jingmai();
        neiGong.JiuYang();
        zhaoShi.QiShangQuan();
    }
}
複製代碼

給外人看到的只有張無忌的出招是七傷拳,可是不知道內部的具體操做,這也就是外觀類的總體展示方式了。 優勢:

  1. 全部的依賴都是出如今外觀類的,子系統間互不干擾。
  2. 具體實現對用戶隱藏,也就是用戶和子系統處於鬆耦合狀態,同時保障了子系統的安全性。 缺點:業務一旦出現變動,就須要直接修改外觀類。

享元模式

使用共享對象有效地支持大量細粒度的對象。

該模式下的對象有

  1. Flyweight:抽象享元角色。
  2. ConcreteFlyweight:具體享元角色
  3. FlyweightFactory:享元工廠,負責對象建立和管理。

其實往簡單了說就是一種緩衝池的技術。

/** * 享元工廠 */
public class VipFactory {
    private static Map<String, Vip> cache = new HashMap<>(); 
    public static Vip getVip(String number){
        if(cache.containsKey(number)){
            return cache.get(number);
        }else{
            Vip vip = new Vip(number);
            cache.put(number, vip);
            return vip;
        }
    }
}

/** * 享元角色 */
public class Vip implements IVip {
    private String name;
    private String number;

    Vip(String number){
        this.number = number;
    }

    @Override
    public void showVip(String number) {
        if (number.equals(number)) {
            System.out.println(name == null? "空": name);
        }
    }
}

/** * 享元抽象角色 */
public interface IVip {
    void showVip(String number);
}
複製代碼

在享元工廠中咱們顯而易見的看到了由static修飾的cache變量,這就是一個緩衝,若是緩衝中存在,就從緩衝中取,不存在則建立。

以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。


相關文章推薦:

聊一聊設計模式(一)-- 六大原則

聊一聊設計模式(二)-- 建立型設計模式

聊一聊設計模式(四)-- 行爲型設計模式

相關文章
相關標籤/搜索