框架設計之設計模式

來源於架構師訓練營第三章,總結。

我們都知道設計模式和基礎設計原則是架構師掌握的基礎知識,就是學java的人掌握java語法一個道理,那我們在日常開發工作中又怎麼對待設計模式呢?我們會刻意的爲了一段代碼去選擇用設計模式嗎?今天我們來說一下設計模式。

什麼是設計模式

想知道什麼是設計模式之前我們需要了解什麼是開發原則,可以通過文章《基礎框架之設計原則》和文章《設計模式之SOLID原則》瞭解一些基礎概念。

設計模式定義:設計模式是描述一種問題的通用解決方案。這種問題在我們的環境中,不停的出現,爲了解決這種問題,抽象出來的一種可以重複使用的解決方案。

設計模式組成部分:一個設計模式總共有四個組成部分;模式名稱:由少量字組成的名稱,有助於表達我們的設計;待解決問題,什麼時候需要用這種設計模式,和運用模式的上下文;解決方案,描述組成的設計元素、關係、職責。一般的解決方案都是抽象的,並不代表具體實現;結論,運用這種方案帶來的利和弊,主要是指系統彈性、擴展性、和可移植性等影響。

設計模式劃分

設計模式一共23種,我們可以通過類型做作用大致分爲三類。

  • 創建型設計模式:主要是對實例化過程的抽象,包括:單例模式、工廠模式、建造者模式、原型模式;

  • 結構型設計模式:將類或者對象結合在一起形成更大的結構,包括:代理模式、橋接模式、裝飾器模式、適配器模式、門面模式、組合模式、享元模式;

  • 行爲型設計模式:對在不同的對象之間劃分責任和算法的抽象畫,包括“觀察者模式、模板模式、策略模式、職責鏈模式、迭代器模式、狀態模式、訪問者模式、備忘錄模式、命令模式、解釋器模式、中介模式;

我們在不瞭解設計模式的情況下有用到設計模式嗎?但肯定是用的,而且用到的設計模式還不少,只是沒有對應到具體的設計模式。

設計模式部分講解

工廠模式

工廠模式包括簡單工廠、工廠方法、抽象工廠這 3 種細分模式。工廠模式用來創建不同但是相關類型的對象(繼承同一父類或者接口的一組子類),由給定的參數來決定創建哪種類型的對象。實際上,如果創建對象的邏輯並不複雜,那我們直接通過 new 來創建對象就可以了,不需要使用工廠模式。當創建邏輯比較複雜,是一個“大工程”的時候,我們就考慮使用工廠模式,封裝對象的創建過程,將對象的創建和使用相分離。

示例:

public class NodeComponentFactory {

    private final static Map<String,NodeParser> cacheParser = new HashMap<>();

    static {
        cacheParser.put(NodeParserEnum.method.name(),new MethodNodeComponent());
        cacheParser.put(NodeParserEnum.bean.name(),new BeanNodeComponent());
        cacheParser.put(NodeParserEnum.condition.name(),new ConditionNodeComponent());
    }

    public static NodeParser getNodeInstance(String nodeName){
        return cacheParser.get(nodeName);
    }
}

單例模式

單例模式用來創建全局唯一的對象。一個類只允許創建一個對象(或者叫實例),那這個類就是一個單例類,這種設計模式就叫作單例模式。單例有幾種經典的實現方式,它們分別是:餓漢式、懶漢式、雙重檢測、靜態內部類、枚舉。

public class FlowContext {
    private static FlowContext instance;
    private FlowContext(){}
    public static FlowContext getInstance(){
        if(instance == null){
            synchronized (FlowContext.class){
                if(instance == null){
                    instance = new FlowContext();
                }
            }
        }
        return instance;
    }
}

適配器模式

適配器提供跟原始類不同的接口。適配器模式是用來做適配的,它將不兼容的接口轉換爲可兼容的接口,讓原本由於接口不兼容而不能一起工作的類可以一起工作。適配器模式有兩種實現方式:類適配器和對象適配器。其中,類適配器使用繼承關係來實現,對象適配器使用組合關係來實現。

public interface Node {
    void setName();
    void setId();
    void setNext();
}
public class MethodNode {
    public void setMethodName(){}
    public void setMethodId(){}
    public void setMethodNext(){}
}
public class BeanNode extends MethodNode implements Node {
    @Override
    public void setName() {
        super.setMethodName();
    }
    @Override
    public void setId() {
        super.setMethodId();
    }
    @Override
    public void setNext() {
        super.setMethodNext();
    }
}

模板模式

模板方法模式在一個方法中定義一個算法骨架,並將某些步驟推遲到子類中實現。模板方法模式可以讓子類在不改變算法整體結構的情況下,重新定義算法中的某些步驟。這裏的“算法”,我們可以理解爲廣義上的“業務邏輯”,並不特指數據結構和算法中的“算法”。這裏的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,這也是模板方法模式名字的由來。

public abstract class AbstractNode {
    public void init(String inputUrl, BaseInput baseInput){
        parser();
        setNodeMap();
    }
    public abstract void parser();
    public abstract void setNodeMap();
}
public class TestNode extends AbstractNode{
    @Override
    public void parser() {
        System.out.println("parser");
    }

    @Override
    public void setNodeMap() {
        System.out.println("setNodeMap");
    }
}

策略模式

策略模式定義一組算法類,將每個算法分別封裝起來,讓它們可以互相替換。策略模式可以使算法的變化獨立於使用它們的客戶端(這裏的客戶端代指使用算法的代碼)。策略模式用來解耦策略的定義、創建、使用。實際上,一個完整的策略模式就是由這三個部分組成的。

public interface Strategy {
    void test();
}
public class TestAStrategy implements Strategy {
    @Override
    public void test() {
        System.out.println("test");
    }
}
public class TestBStrategy implements Strategy {
    @Override
    public void test() {
        System.out.println("test");
    }
}

組合模式

組合模式主要是用來處理樹形結構數據。正因爲其應用場景的特殊性,數據必須能表示成樹形結構,這也導致了這種模式在實際的項目開發中並不那麼常用。但是,一旦數據滿足樹形結構,應用這種模式就能發揮很大的作用,能讓代碼變得非常簡潔。

裝飾器模式

裝飾器模式主要解決繼承關係過於複雜的問題,通過組合來替代繼承,給原始類添加增強功能。這也是判斷是否該用裝飾器模式的一個重要的依據。除此之外,裝飾器模式還有一個特點,那就是可以對原始類嵌套使用多個裝飾器。爲了滿足這樣的需求,在設計的時候,裝飾器類需要跟原始類繼承相同的抽象類或者接口。

public interface IA {
  void f();
}
public class A impelements IA {
    public void f(){ //... }
  }
public class AProxy impements IA {
  private IA a; public AProxy(IA a) { this.a = a; }
  public void f() {
  // 新添加的代理邏輯
  a.f();
  // 新添加的代理邏輯
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章