設計模式 —— 11種行為型設計模式大總結

逐步完善中。。
來源:《圖說設計模式》

行為型模式(Behavioral Pattern)是對在不同的對象之間劃分責任和算法的抽象化。

通過行為型模式,可以更加清晰地劃分類與對象的職責,并研究系統在運行時實例對象之間的交互。在系統運行時,對象并不是孤立的,它們可以通過相互通信與協作完成某些復雜功能,一個對象在運行時也將影響到其他對象的運行。

行為型模式分為類行為型模式和對象行為型模式兩種:

類行為型模式:類的行為型模式使用繼承關系在幾個類之間分配行為,類行為型模式主要通過多態等方式來分配父類與子類的職責。

對象行為型模式:對象行為型模式則使用對象的聚合關聯關系來分配行為,對象行為型模式主要是通過對象關聯等方式來分配兩個或多個類的職責。根據“合成復用原則”,系統中要盡量使用關聯關系來取代繼承關系,因此大部分行為型設計模式都屬于對象行為型設計模式。

包含模式

  • 職責鏈模式(Chain of Responsibility)
    重要程度:3(5為滿分)

  • 命令模式(Command)
    重要程度:4

  • 解釋器模式(Interpreter)
    重要程度:1

  • 迭代器模式(Iterator)
    重要程度:5

  • 中介者模式(Mediator)
    重要程度:2

  • 備忘錄模式(Memento)
    重要程度:2

  • 觀察者模式(Observer)
    重要程度:5

  • 狀態模式(State)
    重要程度:3

  • 策略模式(Strategy)
    重要程度:4

  • 模板方法模式(Template Method)
    重要程度:3

  • 訪問者模式(Visitor)
    重要程度:1

一、職責鏈模式(Chain of Responsibility)

模式動機
模式定義
模式結構
代碼分析
模式分析
實例
優點
缺點
應用
擴展

二、命令模式(Command)

模式動機

在軟件設計中,我們經常需要向某些對象發送請求,但是并不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程序運行時指定具體的請求接收者即可,此時,可以使用命令模式來進行設計,使得請求發送者與請求接收者消除彼此之間的耦合,讓對象之間的調用關系更加靈活。

命令模式可以對發送者和接收者完全解耦,發送者與接收者之間沒有直接引用關系,發送請求的對象只需要知道如何發送請求,而不必知道如何完成請求。這就是命令模式的模式動機。

模式定義

將一個請求封裝為一個對象,從而使我們可用不同的請求對客戶進行參數化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作。命令模式是一種對象行為型模式,其別名為動作(Action)模式或事務(Transaction)模式。

模式結構

命令模式包含如下角色:

Command: 抽象命令類
ConcreteCommand: 具體命令類
Invoker: 調用者
Receiver: 接收者
Client:客戶類

Paste_Image.png
代碼分析
/**
 * 命令接口
 */
public interface Command {
  //執行命令
    public void execute();
  //撤銷命令
    public void undo();
}

package com.test.patten.command;

/**
 * 命令
 */
public class CreateCommand implements Command{
    private Receiver receiver;//命令接收者
    private String state;
    
    public CreateCommand(Receiver receiver){
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.action();
    }

    @Override
    public void undo() {
        receiver.unAction();
    }
    
}

/**
 * 命令接收者,命令真正執行人
 */
public class Receiver {
    public void action(){
        System.out.println("執行命令...");
    }
    
    public void unAction(){
        System.out.println("撤銷命令...");
    }
}
  /**
     * 調用者
     */
public class Invoker {
    private Command command;//命令對象

    /**
     * 設置命令對象
     * @param command
     */
    public void setCommand(Command command) {
        this.command = command;
    }
    /**
     * 執行命令
     */
    public void runCommand(){
        command.execute();
    }
    /**
     * 撤銷命令
     */
    public void unDoCommand(){
        command.undo();
    }
}

  /**
    *客戶端
  */
public class Client {
    public static void main(String[] args){
        //創建接受者
        Receiver receiver = new Receiver();
        //創建命令對象,并設置它的接受者
        Command command = new CreateCommand(receiver);
        
        //創建調用者,將命令對象設置進去
        Invoker invoker = new Invoker();
        invoker.setCommand(command);
        
        //這里可以測試一下
        invoker.runCommand();
        invoker.unDoCommand();
    }
}
模式分析

命令模式的本質是對命令進行封裝,將發出命令的責任和執行命令的責任分割開。

每一個命令都是一個操作:請求的一方發出請求,要求執行一個操作;接收的一方收到請求,并執行操作。

命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是怎么被接收,以及操作是否被執行、何時被執行,以及是怎么被執行的。

命令模式使請求本身成為一個對象,這個對象和其他對象一樣可以被存儲和傳遞。

命令模式的關鍵在于引入了抽象命令接口,且發送者針對抽象命令接口編程,只有實現了抽象命令接口的具體命令才能與接收者相關聯。

應用
  • 工作隊列
  • 線程池
  • 日程安排

三、解釋器模式(Interpreter)

模式動機
模式定義
模式結構
代碼分析
模式分析
實例
優點
缺點
應用
擴展

四、迭代器模式(Iterator)

模式動機

提供一種方法訪問一個容器對象中各個元素,而又不暴露該對象的內部細節。

模式結構
Paste_Image.png
代碼分析
模式分析
實例
優點
缺點
應用

Java集合迭代器

public static void print(Collection coll){  
    Iterator it = coll.iterator();  
    while(it.hasNext()){  
        String str = (String)it.next();  
        System.out.println(str);  
    }  
}  
擴展

五、中介者模式(Mediator)

模式動機
模式定義
模式結構
代碼分析
模式分析
實例
優點
缺點
應用
擴展

六、備忘錄模式(Memento)

模式動機
模式定義
模式結構
代碼分析
模式分析
實例
優點
缺點
應用
擴展

七、觀察者模式(Observer)

模式動機

建立一種對象與對象之間的依賴關系,一個對象發生改變時將自動通知其他對象,其他對象將相應做出反應。在此,發生改變的對象稱為觀察目標,而被通知的對象稱為觀察者,一個觀察目標可以對應多個觀察者,而且這些觀察者之間沒有相互聯系,可以根據需要增加和刪除觀察者,使得系統更易于擴展,這就是觀察者模式的模式動機。

模式定義

定義對象間的一種一對多依賴關系,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知并被自動更新。觀察者模式又叫做發布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。

模式結構

觀察者模式包含如下角色:

Subject: 目標
ConcreteSubject: 具體目標
Observer: 觀察者
ConcreteObserver: 具體觀察者

Paste_Image.png
代碼分析
    // 抽象主題類
   
    public abstract class Subject
    {
        private IList<Observer> observers = new List<Observer>();
       // 增加觀察者
        public void attach(Observer observer)
        {
            observers.Add(observer);
        }

       // 移除觀察者
        public void detach(Observer observer)
        {
            observers.Remove(observer);
        }

    // 向觀察者(們)發出通知
        public void notify()
        {
            foreach (Observer o in observers)
            {
                o.Update();
            }
        }
    }

    
    // 抽象觀察者類,為所有具體觀察者定義一個接口,在得到通知時更新自己
    public abstract class Observer
    {
        public abstract void update();
    }

   // 具體通知者,將有關狀態存入具體觀察者對象;
    public class ConcreteSubject extend Subject
    {
        private string subjectState;
        //省略set和get方法
    }
    // 具體觀察者,實現抽象觀察者角色所要求的更新接口,已是本身狀態與主題狀態相協調
    public class ConcreteObserver extend Observer
    {
        private string observerState;
        private string name;
        private ConcreteSubject subject;

        public ConcreteObserver(ConcreteSubject subject, string name)
        {
            this.subject = subject;
            this.name = name;
        }

      // 實現抽象觀察者中的更新操作
        public void update()
        {
            observerState = subject.getSubjectState();
        }
    }
//客戶端
static void Main(string[] args)
        {
          
            ConcreteSubject subject = new ConcreteSubject();

            subject.attach(new ConcreteObserver(subject, "Observer A"));
            subject.attach(new ConcreteObserver(subject, "Observer B"));
            subject.attach(new ConcreteObserver(subject, "Observer C"));

            subject.setSubjectState("Ready");
            subject.notify();
        }
優點

觀察者模式可以實現表示層和數據邏輯層的分離,并定義了穩定的消息更新傳遞機制,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀察者角色。

觀察者模式在觀察目標和觀察者之間建立一個抽象的耦合。

觀察者模式支持廣播通信。

觀察者模式符合“開閉原則”的要求。

缺點

如果一個觀察目標對象有很多直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。

如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能導致系統崩潰。

觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎么發生變化的,而僅僅只是知道觀察目標發生了變化。

應用

觀察者模式在軟件開發中應用非常廣泛,如某電子商務網站可以在執行發送操作后給用戶多個發送商品打折信息,某團隊戰斗游戲中某隊友犧牲將給所有成員提示等等,凡是涉及到一對一或者一對多的對象交互場景都可以使用觀察者模式。

擴展

MVC模式

MVC模式是一種架構模式,它包含三個角色:模型(Model),視圖(View)和控制器(Controller)。觀察者模式可以用來實現MVC模式,觀察者模式中的觀察目標就是MVC模式中的模型(Model),而觀察者就是MVC中的視圖(View),控制器(Controller)充當兩者之間的中介者(Mediator)。當模型層的數據發生改變時,視圖層將自動改變其顯示內容。

八、狀態模式(State)

模式動機

在很多情況下,一個對象的行為取決于一個或多個動態變化的屬性,這樣的屬性叫做狀態,這樣的對象叫做有狀態的(stateful)對象,這樣的對象狀態是從事先定義好的一系列值中取出的。當一個這樣的對象與外部事件產生互動時,其內部狀態就會改變,從而使得系統的行為也隨之發生變化。

模式結構

狀態模式包含如下角色:

Context: 環境類
State: 抽象狀態類
ConcreteState: 具體狀態類

Paste_Image.png
應用

使用狀態模式可以描述工作流對象(如批文)的狀態轉換以及不同狀態下它所具有的行為。

九、策略模式(Strategy)

模式動機

完成一項任務,往往可以有多種不同的方式,每一種方式稱為一個策略,我們可以根據環境或者條件的不同選擇不同的策略來完成該項任務。

在軟件系統中,有許多算法可以實現某一功能,如查找、排序等,一種常用的方法是硬編碼(Hard Coding)在一個類中,如需要提供多種查找算法,可以將這些算法寫到一個類中,在該類中提供多個方法,每一個方法對應一個具體的查找算法;當然也可以將這些查找算法封裝在一個統一的方法中,通過if…else…等條件判斷語句來進行選擇。這兩種實現方法我們都可以稱之為硬編碼,如果需要增加一種新的查找算法,需要修改封裝算法類的源代碼;更換查找算法,也需要修改客戶端調用代碼。在這個算法類中封裝了大量查找算法,該類代碼將較復雜,維護較為困難。

為了解決這些問題,可以定義一些獨立的類來封裝不同的算法,每一個類封裝一個具體的算法,在這里,每一個封裝算法的類我們都可以稱之為策略(Strategy),為了保證這些策略的一致性,一般會用一個抽象的策略類來做算法的定義,而具體每種算法則對應于一個具體策略類。

模式定義

定義一系列算法,將每一個算法封裝起來,并讓它們可以相互替換。策略模式讓算法獨立于使用它的客戶而變化,也稱為政策模式(Policy)。

策略模式是一種對象行為型模式。

模式結構

策略模式包含如下角色:

Context: 環境類
Strategy: 抽象策略類
ConcreteStrategy: 具體策略類

Paste_Image.png
代碼分析
模式分析
實例
優點
缺點
應用
擴展

十、模板方法模式(Template Method)

模式動機
模式定義
模式結構
代碼分析
模式分析
實例
優點
缺點
應用
擴展

十一、訪問者模式(Visitor)

模式動機
模式定義
模式結構
代碼分析
模式分析
實例
優點
缺點
應用
擴展
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容