中介者模式:

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
標籤:設計模式
上一篇:迭代器模式
