Kimn
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- ###### tags: `Design Pattern` --- # 11/03 ## 行為型模式 - 行為型模式用於描述程序在運行時復雜的流程控制(流程控制語句,例如 if else、switch、for 循環等等),即描述多個類或物件之間怎樣相互協作共同完成單個對像都無法單獨完成的任務,它涉及算法與對象間職責的分配。 - 行為型模式分為==類行為模式、物件行為模式==,==前者採用繼承機制來在類間分配行為,後者採用組合或聚合在物件間分配行為==。 - 由於組合關係或聚合關係比繼承關係耦合度低,滿足"合成複用原則",所以物件行為模式比類行為模式具有更大的靈活性。 - 模板方法、策略模式、命令模式、職責鏈、狀態、觀察者、中介者、迭代器、訪問者、備忘錄、解釋器。以上 11 種,除了模板方法和解釋器是類行為型模式,其他的都是物件行為型模式。 ## 模板方法模式 ### 概述: - 在物件導向程序設計過程中,程序員常常會遇到這種情況:設計一個系統時知道了算法所需的關鍵步驟,而且確定了這些步驟的執行順序,但是某些步驟的具體實現還未知,或者說某些步驟的實現與具體的環境相關。 - 例如,去銀行辦理業務時一般要經過這四個流程:取號、排隊、辦理具體業務、對銀行工作人員進行評分等,其中取號、排隊和對銀行工作人員進行評分的業務對每個客戶都是一樣的,可以在父類中實現(因為可以提高代碼的複用性),但是辦理具體業務卻因人而異,它可能是存款、取款或者轉賬等,可以延遲到子類中實現。 ### 定義: - ==定義一個操作中的算法骨架,而將算法的一些步驟延遲到子類中==,使得子類可以不改變該算法結構的情況下重定義該算法的某些特定步驟。 ### 結構: 模板方法(Template Method)模式包含以下主要角色: - 抽像類(Abstract Class):負責給出一個算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成。 - 模板方法:定義了算法的骨架,按某種順序調用其包含的基本方法。 - 基本方法:它是實現算法各個步驟的方法,是模板方法的組成部分。基本方法又可以分為三種: - 抽象方法(Abstract Method):一個抽象方法由抽像類聲明,並由其具體子類實現,也即要求子類必須重寫。 - 具體方法(Concrete Method):一個具體方法由一個抽像類或具體類聲明並實現,其子類可以進行覆蓋也可以直接繼承。 - 鉤子方法(Hook Method):在抽像類中已經實現,包括用於判斷的邏輯方法和需要子類重寫的空方法兩種。 一般鉤子方法是用於判斷的邏輯方法,這類方法一般為 isXxx ,返回值類型為 boolean 類型。 - 具體子類(Concrete Class):實現抽像類中所定義的抽象方法和鉤子方法,它們是一個頂級邏輯的組成步驟。 ### 案例: :::info - 例:炒菜 - 炒菜的步驟是固定的,分為倒油、熱油、倒蔬菜、倒調味品、翻炒等步驟。現通過模板方法來用代碼模擬。類圖如下: ![](https://i.imgur.com/o1VrOmD.png) ::: ```typescript= // 抽象類(定義模板方法和基本方法) abstract class ABstractClass { pourOil(): void { console.log("倒油"); } heatOil(): void { console.log("熱油"); } // 倒蔬菜是不一樣的(一個下包菜,一個下菜心) abstract pourVegetable(): void; // 第四步:倒調味料是不一樣的 abstract pourSauce(): void; fry(): void { console.log("炒啊炒啊炒啊炒啊"); } // 模板方法定義 cookProcess(): void { this.pourOil(); this.heatOil(); this.pourVegetable(); this.pourSauce(); this.fry(); } } // 具體子類 class ConcreteClass_Cabbage extends ABstractClass { pourVegetable(): void { console.log("下鍋的蔬菜是包菜"); } pourSauce(): void { console.log("下鍋的醬料是辣椒"); } } class ConcreteClass_Chon extends ABstractClass { pourVegetable(): void { console.log("下鍋的蔬菜是菜心"); } pourSauce(): void { console.log("下鍋的醬料是蒜蓉"); } } class Client { static main(): void { // 炒包菜 // 創建物件 const cabbage = new ConcreteClass_Cabbage(); // 調用炒菜的功能 cabbage.cookProcess(); } } Client.main(); ``` ### 優缺點、適用場景: #### 優點: - 提高代碼復用性:將相同部分放在抽象的父類中,而將不同的代碼放入不同的子類中。 - ==實現反轉控制==:通過一個父類調用其子類的操作,通過對子類的具體實現擴展不同的行為,實現了反向控制,並符合“開閉原則”。 #### 缺點: - 對每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象。 - 父類中的抽象方法由子類實現,子類執行的結果會影響父類的結果,者會導致一種反向的控制結構。 #### 適用場景: - 算法的整體步驟很固定,但其中個別部分易變時,這時候可以使用模板方法模式,將容易變得部分抽象出來,供子類實現。 - 需要通過子類來決定父類算法中某個步驟是否執行,實現子類對父類的反向控制。 這裡其實會涉及到鉤子函數,也就是說如果有這樣的一個場景的話,那麼我們就需要定義鉤子函數了,只不過上述案例中並沒有體現出來,這是因為我們的業務需求裡面並不需要用到鉤子函數。後期我們在做其他業務時,就可能需要定義鉤子函數了。 ## 策略模式 ### 概述: - 我們去旅遊選擇出行方式能有很多種,可以騎自行車、可以坐汽車、可以坐火車、可以坐飛機。 ![](https://i.imgur.com/V4yB2wo.png) - 開發需要選擇一款開發工具,可以進行代碼開發的工具有很多,可以選擇 Idea 進行開發,也可以使用 eclipse 進行開發,也可以使用其他的一些開發工具。 ![](https://i.imgur.com/N3B9Vua.png) ### 定義: - 該模式定義了一系列算法,並將每個算法封裝起來,使他們可以相互替換,且算法的變化不會影響使用算法的客戶。策略模式屬於物件行為模式,它通過對算法進行封裝,把使用算法的責任和實現分割出來,並委派給不同的物件對這些算法進行管理。 ### 結構: 策略模式的主要角色如下: - 抽象策略(Strateqy)類:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。 - 具體策略(Concrete Strateqy)類:實現了抽象策略定義的接口,提供具體的算法實現或行為。 - 環境(Context)類:持有一個策略類的引用,最終給客戶端調用。 ### 案例: :::info 促銷活動: - 一家百貨公司在定年度的促銷活動。針對不同的節日(春節、中秋節、聖誕節)推出不同的促銷活動,由促銷員將促銷活動展示給客戶。類圖如下: ![](https://i.imgur.com/WWBhwoZ.png) ::: ```typescript= // 抽象策略類 interface Strategy { show(): void; } // 具體策略類,封裝算法 class StrategyA implements Strategy { show(): void { console.log("買一送一"); } } class StrategyB implements Strategy { show(): void { console.log("滿200減50"); } } class StrategyC implements Strategy { show(): void { console.log("滿1000元加一元換購任意200元以下商品"); } } // 銷售員:環境角色(Context) class SalesMan { // 聚合策略類物件 private _strategy: Strategy; public get strategy(): Strategy { return this._strategy; } public set strategy(value: Strategy) { this._strategy = value; } constructor(strategy: Strategy) { this._strategy = strategy; } // 由促銷員展示促銷活動給用戶 salesManShow(): void { this._strategy.show(); } } class Client { static main(): void { // 春節,使用春節促銷活動 const salesman = new SalesMan(new StrategyA()); // 展示促銷活動 salesman.salesManShow(); salesman.strategy = new StrategyB(); salesman.salesManShow(); salesman.strategy = new StrategyC(); salesman.salesManShow(); } } Client.main(); ``` ### 優點缺點: - 優點: - 策略類之間可以自由切換:由於策略類都實現同一個接口,所以使他們之間可以自由切換。 - 易於擴展:增加一個新的策略只需要添加一個具體的策略類即可,基本不需要改變原有的代碼,符合“開閉原則” - ==避免使用多重條件選擇語句(if else)==,充分體現物件導向設計思想。 - 缺點: - 客戶端必須知道所有策略類,並自行決定使用哪一個策略類。 - 策略模式將造成產生很多策略類,可以通過使用享元模式在一定程度上減少物件的數量。 ### 使用場景: - 一個系統需要動態的在幾種算法中選擇一種時,可將每個算法封裝到策略類中。 - 一個類定義了多種行為,並且這些行為在這個類的操作中以多個條件語句的形式出現,可將每個條件分支移入他們各自的策略類中以代替這些條件語句。 - 系統中各算法彼此完全獨立,且要求對客戶隱藏具體算法的實現細節時。 - 多個類只區別在表現行為不同,可以使用策略模式,在運行時動態選擇具體要執行的行為。

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully