主頁 > 軟體設計 > 行為型設計模式(中)

行為型設計模式(中)

2020-09-15 04:26:44 軟體設計

中介者模式:

  1、定義:用一個中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互參考,

        從而使其耦合松散,而且可以獨立地改變它們之間的互動

  2、模型結構:

    (1)抽象中介者(Mediator):它是中介者的介面,提供了同事物件注冊與轉發同事物件資訊的抽象方法

    (2)具體中介者(ConcreteMediator):實作中介者介面,通過一個資料結構來管理同事物件

                          協調各個同事角色之間的互動關系,因此它依賴于同事角色

    (3)抽象同事類(Colleague):定義同事類的介面,保存中介者物件,提供同事物件互動的抽象方法,

                     實作所有相互影響的同事類的公共功能

    (4)具體同事類(Concrete Colleague):抽象同事類的實作者,當與其他同事物件互動時,中介者物件負責后續的互動

  3、優點:

    (1)降低了物件之間的耦合性,使得物件易于獨立地被復用

    (2)將物件間的一對多關聯轉變為一對一的關聯,提高系統的靈活性,使得系統易于維護和擴展

    (3)減少子類生成

  4、缺點:當同事類太多時,中介者的職責將很大,它會變得復雜而龐大,以至于系統難以維護

  5、適用環境:

    (1)當物件之間存在復雜的網狀結構關系而導致依賴關系混亂難以復用

    (2)當想創建一個運行于多個類之間的物件,又不想生成新的子類時

// 抽象中介者abstract class Mediator {    abstract register(colleague: Colleague): void;    abstract relay(colleague: Colleague): void;}// 具體中介者class ConcreteMediator extends Mediator {    // 儲存同事類集合    private colleagues: Set<Colleague> = new Set<Colleague>();    // 添加未加入的同事并設定中介    register(colleague: Colleague): void {        if (!this.colleagues.has(colleague)) {            this.colleagues.add(colleague);            colleague.setMedium(this);          }    }    // 中介接受請求    relay(colleague: Colleague): void {        if (this.colleagues.has(colleague)) {            colleague.receive();        }    }}// 抽象同事類abstract class Colleague {    protected mediator: Mediator;   // 中介物件    protected colleague: Colleague; // 要查詢的同事物件    protected phone: string;    // 查詢內容    constructor(phone: string) {        this.phone = phone;    }    // 設定中介    setMedium(mediator: Mediator): void {        this.mediator = mediator;    }    abstract searchColleague(colleague: Colleague): void;   // 查詢同事    abstract receive(): void;   // 接受請求    abstract send(): void;  // 發送請求}// 具體同事類class Tom extends Colleague {    constructor(phone: string) {        super(phone);    }    searchColleague(colleague: Colleague): void {        this.colleague = colleague;    }    receive(): void {        console.log(`Tom 收到請求,,電話號碼為${this.phone}`);    }    send(): void {        console.log("Tom 發出電話查詢請求");        this.mediator.relay(this.colleague);    }}class Jerry extends Colleague {    constructor(phone: string) {        super(phone);    }    searchColleague(colleague: Colleague): void {        this.colleague = colleague;    }    receive(): void {        console.log(`Jerry 收到請求,電話號碼為${this.phone}`);    }    send(): void {        console.log("Jerry 發出電話查詢請求");        this.mediator.relay(this.colleague);    }}let mediator: Mediator = new ConcreteMediator();let colleague1: Colleague = new Tom("1234567");let colleague2: Colleague = new Jerry("2234567");// 設定相同的中介mediator.register(colleague1);mediator.register(colleague2);colleague1.searchColleague(colleague2); // Tom 查詢 Jerrycolleague2.searchColleague(colleague1); // Jerry 查詢 Tomcolleague1.send();console.log("--------------------------");colleague2.send();

 

備忘錄模式:

  1、定義:在不破壞封裝性的前提下,捕獲一個物件的內部狀態,并在該物件之外保存這個狀態,

        以便以后當需要時能將該物件恢復到原先保存的狀態

  2、模型結構:

    (1)發起人(Originator):記錄當前時刻的內部狀態資訊,提供創建備忘錄和恢復備忘錄資料的功能

                   實作其他業務功能,它可以訪問備忘錄里的所有資訊

    (2)備忘錄(Memento):負責存盤發起人的內部狀態,在需要的時候提供這些內部狀態給發起人

    (3)管理者(Caretaker):管理備忘錄,提供保存與獲取備忘錄的功能,但其不能對備忘錄的內容進行訪問與修改

  3、優點:

    (1)提供了一種可以恢復狀態的機制:當用戶需要時能夠比較方便地將資料恢復到某個歷史的狀態

    (2)實作了內部狀態的封裝:除了創建它的發起人之外,其他物件都不能夠訪問這些狀態資訊

    (3)簡化了發起人類:發起人不需要管理和保存其內部狀態的各個備份,所有狀態資訊都保存在備忘錄中,

                并由管理者進行管理,這符合單一職責原則

  4、缺點:資源消耗大,如果要保存的內部狀態資訊過多或者特別頻繁,將會占用比較大的記憶體資源

  5、適用環境:

    (1)需要保存與恢復資料的場景

    (2)需要提供一個可回滾操作的場景

// 學生成績class Grade {    private no: string; // 學號    private grade: number;  // 成績    constructor(no: string, grade: number) {        this.no = no;        this.grade = grade;    }    // 輸出學號和成績    printGrade(): void {        console.log(`學號:${this.no},成績:${this.grade}`);    }}// 備忘錄class Memento {    private grades: Grade[];    constructor(grades: Grade[]) {        this.grades = grades;    }    // 設定成績狀態    setState(grades: Grade[]): void {        this.grades = grades;    }    // 獲取成績狀態    getState(): Grade[] {        return this.grades;    }}// 發起人class Originator {    private grades: Grade[];    setState(grades: Grade[]): void {        this.grades = grades;    }    getState(): Grade[] {        return this.grades;    }    // 輸出成績狀態    printState(): void {        for (let grade of this.grades) {            grade.printGrade();        }    }    createMemento(): Memento {        return new Memento(this.grades);    }    restoreMemento(mem: Memento): void {        this.setState(mem.getState());    }}// 管理者class Caretaker {    private memento: Memento = null;    setMemento(mem: Memento): void {        this.memento = mem;    }    getMemento(): Memento {        return this.memento;    }}// 初始化學生成績let grades: Grade[] = new Array<Grade>();let temp: Grade[] = new Array<Grade>();for (let i: number = 0; i < 3; ++i) {    grades.push(new Grade(String(i+1), 2019+i));    temp.push(new Grade(String(i+2), i+1));}let ori: Originator = new Originator();let cr: Caretaker = new Caretaker();ori.setState(grades);console.log("初始狀態:")ori.printState();cr.setMemento(ori.createMemento()); // 保存狀態// 不能只修改 grades 陣列再然后把該陣列設定為新狀態,因為陣列是參考型別ori.setState(temp);console.log("新的狀態:");ori.printState();ori.restoreMemento(cr.getMemento());    // 恢復狀態console.log("恢復狀態:");ori.printState();

 

觀察者模式:

  1、定義:定義物件間的一種一對多依賴關系,使得每當一個物件狀態發生改變時,

        其相關依賴物件皆得到通知并被自動更新

  2、模型結構:

    (1)抽象目標(Subject):提供了一個用于保存觀察者物件的聚集類和增加、洗掉觀察者物件的方法,

                  以及通知所有觀察者的抽象方法

    (2)具體目標(Concrete Subject):它實作抽象目標中的通知方法,當具體目標的內部狀態發生改變時,

                        通知所有注冊過的觀察者物件

    (3)抽象觀察者(Observer):它是一個抽象類或介面,它包含了一個更新自己的抽象方法

                    當接到具體主題的更改通知時被呼叫

    (4)具體觀察者(Concrete Observer):實作抽象觀察者中定義的抽象方法

  3、優點:

    (1)降低了目標與觀察者之間的耦合關系,兩者之間是抽象耦合關系

    (2)目標與觀察者之間建立了一套觸發機制

  4、缺點:

    (1)目標與觀察者之間的依賴關系并沒有完全解除,而且有可能出現回圈參考

    (2)當觀察者物件很多時,通知的發布會花費很多時間,影響程式的效率

  5、適用環境:

    (1)物件間存在一對多關系,一個物件的狀態發生改變會影響其他物件

    (2)當一個抽象模型有兩個方面,其中一個方面依賴于另一方面時,

      可將這二者封裝在獨立的物件中以使它們可以各自獨立地改變和復用

// 抽象目標,抽象售賣火車票物件abstract class Subject {    protected observers: Observer[] = new Array<Observer>();    // 增加觀察者    add(observer: Observer): void {        this.observers.push(observer);    }    // 洗掉觀察者    remove(observer: Observer): void {        let idx = this.observers.indexOf(observer);        // 若找到該觀察者,則洗掉掉它        if (idx > -1)            this.observers.splice(idx, 1);    }    abstract notifyObserver(num: number): void;}// 具體目標,具體售賣火車票物件class ConcreteSubjext extends Subject {    private fare_num: number = 100;    notifyObserver(num: number): void {        for (let obs of this.observers) {            this.fare_num = this.fare_num - num;            obs.response(num, this.fare_num);        }    }}// 抽象觀察者interface Observer {    response(num: number, fare_num: number): void;}// 具體觀察者class ConcreteObserver1 implements Observer {    response(num: number, fare_num: number): void {        console.log("------------------In obs1-----------------------");        num > 0 ? console.log(`火車票賣出 ${num} 張`) : console.log(`火車票退回 ${-num} 張`);        console.log(`剩余 ${fare_num} 張票`);    }}class ConcreteObserver2 implements Observer {    response(num: number, fare_num: number): void {        console.log("------------------In obs2-----------------------");        num > 0 ? console.log(`火車票賣出 ${num} 張`) : console.log(`火車票退回 ${-num} 張`);        console.log(`剩余 ${fare_num} 張票`);    }}let subject: Subject = new ConcreteSubjext();let obs1: Observer = new ConcreteObserver1();let obs2: Observer = new ConcreteObserver2();subject.add(obs1);subject.add(obs2);subject.notifyObserver(4);subject.notifyObserver(-2);subject.remove(obs1);subject.notifyObserver(10);

 

狀態模式:

  1、定義:對有狀態的物件,把復雜的“判斷邏輯”提取到不同的狀態物件中,

        允許狀態物件在其內部狀態發生改變時改變其行為

  2、模型結構:

    (1)環境(Context):也稱為背景關系,它定義了客戶感興趣的介面,維護一個當前狀態

                并將與狀態相關的操作委托給當前狀態物件來處理

    (2)抽象狀態(State):定義一個介面,用以封裝環境物件中的特定狀態所對應的行為

    (3)具體狀態(Concrete State):實作抽象狀態所對應的行為

  3、優點:

    (1)狀態模式將與特定狀態相關的行為區域化到一個狀態中,并將不同狀態的行為分割開,滿足“單一職責原則”

    (2)將不同的狀態引入獨立的物件中會使得狀態轉換變得更加明確,且減少物件間的相互依賴

    (3)有利于程式的擴展,通過定義新的子類很容易地增加新的狀態和轉換

  4、缺點:

    (1)狀態模式的使用必然會增加系統類和物件的個數

    (2)狀態模式的結構與實作都較為復雜,如果使用不當將導致程式結構和代碼的混亂

  5、適用環境:

    (1)當一個物件的行為取決于它的狀態,并且它必須在運行時根據狀態改變它的行為時,就可以考慮使用狀態模式

    (2)一個操作中含有龐大的分支結構,并且這些分支決定于物件的狀態

// 環境類class StateContext {    private state: State;    private grade: number;    // 默認為 A 類,運行時先檢查符合哪個類    constructor() {        this.state = new ConcreteStateA();      }    // 設定狀態    setState(): void {        if (this.grade > 50)            this.state = new ConcreteStateA();        else if (this.grade <= 50)            this.state = new ConcreteStateB();    }    // 獲取狀態    getState(): State {        return this.state;    }    // 處理輸入的成績    Handle(grade: number): void {        this.grade = grade;        this.setState();        this.state.Handle();    }}// 抽象狀態類abstract class State {    protected context: StateContext;    // 環境物件    protected stateName: string;    // 狀態名    Handle(): void {        console.log(context.getState().stateName);    };}class ConcreteStateA extends State {    constructor() {        super();        this.stateName = "-----------------ConcreteStateA---------------";    }}class ConcreteStateB extends State {    constructor() {        super();        this.stateName = "-----------------ConcreteStateB---------------";    }}let context: StateContext = new StateContext();context.Handle(90); // -----------------ConcreteStateA---------------context.Handle(50); // -----------------ConcreteStateB---------------context.Handle(70); // -----------------ConcreteStateA---------------context.Handle(30); // -----------------ConcreteStateB---------------

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/42134.html

標籤:設計模式

上一篇:迭代器模式

下一篇:設計模式 - 單例模式(詳解)看看和你理解的是否一樣?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more