摘要:設計模式分創建型模式,結構型模式和行為型模式。責任鏈模式使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關系。狀態模式的核心是封裝,通過狀態的變更引起行為的變更。
前言
最近加班是真的很多,無法騰出大塊時間來學習。設計模式又不想只更到一半半途而廢,想了又想,決定精簡,保證大家一看就懂(看完就忘...)。設計模式分創建型模式,結構型模式和行為型模式。到目前為止,創建型模式已經講完,對于剩下的模式,會分成這兩大塊統一講解。
行為型模式行為型模式主要關注的點事類的動作,各個類之間相互的作用,將職責劃分清楚,使我們的代碼更加的清晰。
策略模式定義一組算法,將每個算法都封裝起來,并且使他們之間可以互換。
策略模式是一個出現頻率很高,但又很簡單的模式。下面的場景是我們要出去旅游,但是可以選擇出去旅游的交通方式,比如坐飛機,坐火車或者步行。廢話不再多說,直接上碼:
public interface Strategy { void travel(); }
public class Walk implements Strategy { @Override public void travel() { System.out.println("步行去旅行"); } }
public class Train implements Strategy { @Override public void travel() { System.out.println("坐火車去旅行"); } }
public class Airplane implements Strategy { @Override public void travel() { System.out.println("坐著飛機去旅行"); } }
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void execute(){ strategy.travel(); } }
public class Client { public static void main(String[] args) { Context context = new Context(new Airplane()); context.execute(); } } console: 坐著飛機去旅行
策略模式的優點非常明顯,在現有的系統中增加一個策略太容易,只要實現接口就可以了,其他都不用修改,類似于一個可以反復拆卸的插件,符合ocp原則。其缺點就是每個策略都是一個類,復用性很小,復雜的業務場景容易發生類數量爆炸,并且策略模式和迪米特法則是違背的,我們看下上面的clent場景類(相當于項目中的高層調用模塊),我只是想使用一個策略,憑什么就要了解這個策略呢?那要封裝類就沒有意義了,這是策略模式的一個大缺點,所以策略模式很少多帶帶出現,大多結合其他模式來彌補這個缺陷,如工廠方法或者代理模式。
觀察者模式定義對象間一種一對多的依賴關系,使得每當一個對象改變狀態,則所有依賴于它的對象都會得到通知并被自動更新
策略模式也叫發布訂閱模式,其中最主要額角色名稱就是subject被觀察者和observer觀察者。接下來會模擬一個場景,學校作為被觀察者發布放假的消息,家長和學生作為觀察者實現自己的邏輯:
/** * 主題(被觀察者)需要實現的職責,就是可以動態的增加刪除觀察者。 * 根據主題的狀態通知所有的觀察者Observer */ public abstract class Subject { private VectorobserverList = new Vector<>(); private int status; public void addObserver(Observer observer){ observerList.add(observer); } public void delObserver(Observer observer){ observerList.remove(observer); } public void notifyAllObserver(){ observerList.forEach(observer -> { observer.update(); }); } }
public class SchoolSubject extends Subject { //學校宣布放七天假期 public void haveSevenDaysHoliday(){ System.out.println("學校:從今天開始放假,所有學生七天后返校"); super.notifyAllObserver(); } }
public interface Observer { //觀察者,被通知了實現其自己的邏輯 void update() ; }
public class Parent implements Observer { @Override public void update() { System.out.println("家長:這倒霉孩子怎么又放假了,堅決不能讓他玩王者榮耀...."); } }
public class Student implements Observer { @Override public void update() { System.out.println("學生:哇哈哈,終于有時間打王者榮耀嘍"); } }
public class Client { public static void main(String[] args) { SchoolSubject subject = new SchoolSubject(); Student student = new Student(); Parent parent = new Parent(); subject.addObserver(student); subject.addObserver(parent); subject.haveSevenDaysHoliday(); } } console: 學校:從今天開始放假,所有學生七天后返校 學生:哇哈哈,終于有時間打王者榮耀嘍 家長:這倒霉孩子怎么又放假了,堅決不能讓他玩王者榮耀....
雖說觀察者和被觀察者是耦合在一起的,但是不管是擴展增加觀察者還是被觀察者都非常容易。并且根據單一職責原則,每個類的職責都是唯一,需要一套機制將類串聯起來形成一個真實的場景,就比如學校公布放假,孩子想著玩游戲,家長為了孩子的成績禁止孩子玩游戲,然后因為學校放假我就不玩了(小學生,你懂得),這樣就形成了一個觸發機制。其缺點就是執行效率低下,需異步執行。從原理上看,我們常用的mq就是觀察者模式的升級版。
責任鏈模式使多個對象都有機會處理請求,從而避免了請求的發送者和接受者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有對象處理它為止。
責任鏈我們很容易想到鏈表結構,實際上責任鏈就是一種基于鏈表的處理方式。當一個請求過來,調用鏈表的頭結點,處理之后再往后流轉。
有這么一個場景:路飛餓了打開美團準備訂外賣。選中吃的后,進行下單,首先校驗是否在營業時間內,然后校驗是否在配送范圍內,然后校驗是否有貨等等,設定責任鏈都通過后,路飛才能訂到飯。
//鏈表內結點的基類 public abstract class RuleHandler { protected RuleHandler successor; public abstract void echo(Context context); public void setSuccessor(RuleHandler successor) { this.successor = successor; } public RuleHandler getSuccessor() { return successor; } }
//判斷營業時間 public class TimeHandler extends RuleHandler { @Override public void echo(Context context) { //營業時間判斷 if (context.isTimeInRange()){ if (this.getSuccessor()!=null){ this.getSuccessor().echo(context); } }else { throw new RuntimeException("不在營業時間內"); } } }
//判斷是否在配送范圍內 public class AreaHanler extends RuleHandler { @Override public void echo(Context context) { if (context.isAreaInRange()){ if (this.getSuccessor()!=null){ this.getSuccessor().echo(context); } }else { throw new RuntimeException("不在配送范圍內"); } } }
//判斷庫存 public class StockHandler extends RuleHandler { @Override public void echo(Context context) { if (context.hasStock()){ if (this.getSuccessor()!=null){ this.getSuccessor().echo(context); } }else { throw new RuntimeException("挑選的商品已經賣完"); } } }
客戶端調用邏輯:
public class Client { public static void main(String[] args) { RuleHandler timeHandler = new TimeHandler(); RuleHandler areaHandler = new AreaHanler(); RuleHandler stockHandler = new StockHandler(); timeHandler.setSuccessor(areaHandler); areaHandler.setSuccessor(stockHandler); timeHandler.echo(new Context()); } }
代碼非常簡單,責任鏈模式的重點是在鏈上,由一條鏈去處理請求并返回相應的結果。它非常顯著的優點就是將請求和處理分開,兩者解耦,提高系統的靈活性。缺點就是鏈表遍歷必須從鏈頭到鏈尾,存在性能問題。采用了類似遞歸調用的方式,增大了讀懂邏輯的難度
模板方法模式在之前的博客里已經長篇大論過,故直接拿過來。
模板方法
當一個對象內在狀態改變時允許其改變行為,這個對象看起來像改變了其類。
狀態模式的核心是封裝,通過狀態的變更引起行為的變更。現在大家來思考一下,電腦有三種狀態,分別為關機,已啟動。
//代表環境,也就是狀態的主體 public class Context { //所有的電腦狀態 public final static OpenState OPEN = new OpenState(); public final static CloseState CLOSE = new CloseState(); //電腦當前的狀態 private ComputerState currentState; public ComputerState getCurrentState() { return currentState; } public void setCurrentState(ComputerState currentState) { this.currentState = currentState; this.currentState.setContext(this); } public void openMachine() { this.currentState.openMachine(); } public void closeMachine() { this.currentState.closeMachine(); } }
//狀態基類,真實的電腦邏輯封裝在了狀態中 public abstract class ComputerState { protected Context context; public void setContext(Context context) { this.context = context; } public abstract void openMachine(); public abstract void closeMachine(); }
public class OpenState extends ComputerState{ @Override public void openMachine() { System.out.println("電腦開機..."); } @Override public void closeMachine() { super.context.setCurrentState(Context.CLOSE); super.context.getCurrentState().closeMachine(); } }
public class CloseState extends ComputerState { @Override public void openMachine() { super.context.setCurrentState(Context.OPEN); super.context.getCurrentState().openMachine(); } @Override public void closeMachine() { System.out.println("電腦關機..."); } }
客戶端測試類:
public class Client { public static void main(String[] args) { Context context = new Context(); context.setCurrentState(Context.OPEN); context.openMachine(); context.closeMachine(); } }
狀態模式的優點有結構清晰,避免了各種條件的判斷,省掉了swtich...case,if...else語句的使用,提升了代碼的可讀性。遵循了單一職責原則和開閉原則,每個狀態都是一個子類,增加狀態只需增加一個狀態子類,修改狀態,修改對應的子類就可以了。封裝性非常好,客戶端不需知道內部狀態的轉換以及相應的邏輯.其缺點就是狀態子類會太多,并且我們可以將狀態存儲到數據庫中,然后根據狀態執行相應的操作,這也是一種不錯的實現方式,具體如何使用看大家個人喜好了。
總結本章的行為型模式總結了策略模式、觀察者模式、責任鏈模式、模板方法模式和狀態模式,其實不僅于此,還有備忘錄模式和命令模式等,但因其使用場景有限,就不做一一探討了,留給讀者自己學習~.~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68293.html
摘要:推文用設計模式解構三國是一種什么體驗行為型設計模式一策略模式工廠模式優化結構狀態模式隨著狀態改變而改變行為。推文狀態機與狀態模式責任鏈模式多個對象依次處理請求前者指定后者。代理模式代理針對一個對象,為了增加控制等中介雙方都是多個,為了解耦。 策略模式 選擇使用封裝好的一系列算法,可相互替換。 類比:商店[Context]買完衣服買單[Stratege](現金[Concrete Stra...
摘要:設計模式的類別設計模式一共分為種類型,共種。屬于結構型的設計模式適配器模式橋接模式裝飾模式組合模式外觀模式享元模式代理模式。問題描述了應該在何時使用設計模式。解決方案描述了設計的組成成分,它們之間的相互關系及各自的職責和協作方式。 設計模式概述 1. 設計模式是什么 我們在平時編寫代碼的過程中,會遇到各種各樣的問題,細想一下很多問題的解決思路大致一樣的,這時候你就可以把解決問題的思路整...
閱讀 3021·2023-04-25 18:00
閱讀 2222·2021-11-23 10:07
閱讀 4060·2021-11-22 09:34
閱讀 1250·2021-10-08 10:05
閱讀 1572·2019-08-30 15:55
閱讀 3435·2019-08-30 11:21
閱讀 3339·2019-08-29 13:01
閱讀 1378·2019-08-26 18:26