設計模式-策略模式(Strategy Model)

来源:http://www.cnblogs.com/vincentzh/archive/2016/10/15/5964947.html
-Advertisement-
Play Games

淺析設計模式中的策略模式,包含原理解讀和具體案例代碼的實現。僅為個人學習總結分享,希望圍觀者多提意見。 ...


1、概述

    在開發過程中常常會遇到類似問題,實現一個功能的時候往往有多種演算法/方法(策略),我們可以根據環境的不同來使用不同的演算法或策略來實現這一功能。     如在人物比較排序的實現中,我們有時需要把年齡做為比較的標準,或者有時又想將身高作為比較的標準,不同的比較標準也就衍生出了統一個比較目的的不同演算法實現,在搜索問題中也是類似,有可能用到二分查找、順序查找之類。通常較簡單直接的思維便是將所有的演算法(策略)寫成一個類的方法,再通過客戶端去調用;也可一將所有的演算法全部封裝在一個方法中用一堆的if...else...語句來判斷。如果需要增加一種演算法時,就需要去修改封裝演算法類的源代碼;更換比較排序演算法時,又需要去修改客戶端代碼。在演算法類中封裝了大量的演算法,該類代碼較複雜,維護困難;而且將策略包含在客戶端,將導致客戶端的程式龐大難以維護。   案例:出行旅游:出行旅游時,我們有以下幾個策略可供選擇:自行車、汽車、火車、飛機等,不同的方式,單都是去實現旅行這一個目的,選擇策略的依據是時間、金錢、方便程度(對應到工程中就是需求的環境)。  

2、目的

    策略模式的目的在於:使演算法和對象分離開來,能讓演算法獨立於對象去變化。     核心思想其實是利用了面向對象編程多態的使用。  

3、適用場景

    當存在一下情況時使用Strategy模式:   1)許多類實現統一目的,僅方式不同。“策略”提供了一種用多個行為中的一種來配置類的實現的方法,及一個系統可以動態的在多個演算法中選擇其中一種;   2)需要同一中演算法的不同變體。如:在比較對象時,採用的比較演算法的不同,有可能需要去比較對象的成員變數;   3)一個類或者方法中定義了多種行為,並且這些行為以多個判斷語句來相互切換。可將相關的條件分支移入各自的Strategy類中去實現。   4)演算法的封裝。通過策略模式向使用演算法的客戶隱藏演算法的具體實現。  

4、結構與組成

  策略模式的結構主要分類三個部分:   抽象策略類(Strategy)定義所有實現演算法的公共介面,Context直接使用介面調用ConcreteStrategy的具體演算法。   具體策略類(ConcreteStrategy)實現具體的演算法,每個具體的演算法類必須實現Strategy介面。   環境類(Context)具體演算法的使用類,需要用指定的一個ConcreteStrategy來配置。

 

 

4、實現

  一個班級的若幹個學生,對他們進行排序分別按照名字、年齡、id排序(正序和倒序兩種方式),如年齡和名字重覆,則使用id進行升序排序。
  1 package com.cnblogs.vicentzh.strategymodel;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Collections;
  5 import java.util.Comparator;
  6 import java.util.Iterator;
  7 import java.util.List;
  8 
  9 public class StrategyModel
 10 {
 11     /**
 12      * @Describe 客戶端程式
 13      * @param args
 14      */
 15     public static void main(String[] args)
 16     {
 17         Student p1 = new Student("Tom",1,20);
 18         Student p2 = new Student("Tonny",2,50);
 19         Student p3 = new Student("Tom",5,30);
 20         Student p4 = new Student("John",8,10);
 21         Student p5 = new Student("Susan",9,15);
 22 
 23         List<Student> students = new ArrayList<Student>();
 24         students.add(p1);
 25         students.add(p2);
 26         students.add(p3);
 27         students.add(p4);
 28         students.add(p5);
 29 
 30         Context env = new Context();
 31 
 32         //正序排列
 33         UpNameSort uns = new UpNameSort();
 34         env.setSortStrategy(uns);
 35         env.sort(students);
 36 
 37         for (Iterator<Student> iter=students.iterator(); iter.hasNext();)
 38         {
 39             Student student = iter.next();
 40             System.out.println("id: " + student.getId() + ", name: " + student.getName()
 41                     + ", age:" + student.getAge());
 42         }
 43         System.out.println("-----------------------");
 44         
 45         //倒序排列
 46         DownNameSort dns = new DownNameSort();
 47         env.setSortStrategy(dns);
 48         env.sort(students);
 49 
 50         for (Iterator<Student> iter=students.iterator(); iter.hasNext();)
 51         {
 52             Student student = iter.next();
 53             System.out.println("id: " + student.getId() + ", name: " + student.getName()
 54                     + ", age:" + student.getAge());
 55         }
 56 
 57     }    
 58 }
 59 
 60 
 61 //需要用到的具體實例類
 62 class Student
 63 {
 64     private String name;
 65     private int age;
 66     private int id;
 67     
 68     public Student(String name, int age, int id)
 69     {
 70         this.name = name;
 71         this.age = age;
 72         this.id = id;
 73     }
 74     
 75     public String getName()
 76     {
 77         return name;
 78     }
 79     public int getAge()
 80     {
 81         return age;
 82     }
 83     public int getId()
 84     {
 85         return id;
 86     }    
 87 }
 88 
 89 
 90 //抽象策略類(Strategy),即策略介面
 91 interface SortStrategy
 92 {
 93     public void sortStudent(List<Student> students);
 94 }
 95 
 96 
 97 //具體策略類(ConcreteStrategy),即具體正序演算法實現類
 98 class UpNameSort implements SortStrategy,Comparator<Student>
 99 {
100     @Override
101     public void sortStudent(List<Student> students)
102     {
103         Collections.sort(students, this);
104     }
105     
106     @Override
107     public int compare(Student o1, Student o2)
108     {
109         int result = o1.getName().compareTo(o2.getName());
110         if(0==result)
111         {
112             return o1.getId() - o2.getId();
113         }
114         return result;
115     }
116 }
117 
118 //具體策略類(ConcreteStrategy),即具體倒序演算法實現類
119 class DownNameSort implements SortStrategy, Comparator<Student>
120 {
121     @Override
122     public void sortStudent(List<Student> students)
123     {
124         Collections.sort(students, this);
125         
126     }
127     
128     @Override
129     public int compare(Student o1, Student o2)
130     {
131         int result = o2.getName().compareTo(o1.getName());
132         if(0==result)
133         {
134             return o1.getId() - o2.getId();
135         }
136         return result;
137     }
138 }
139 
140 //使用環境類(Context)
141 //環境類根據接收到客戶端具體的策略來對對象進行使用,同樣也能用setSortStrategy方法
142 //隨時根據客戶端的需求去改變策略演算法,並且不影響對象。
143 class Context
144 {
145     private SortStrategy concreteStrategy; //使用策略配置環境類
146     
147     public Context(SortStrategy conSortStrategy)
148     {
149         this.concreteStrategy = conSortStrategy;
150     }
151     
152     public Context()
153     {
154         
155     }
156     
157     //可隨意定製化具體策略
158     public void setSortStrategy(SortStrategy conSortStrategy)
159     {
160         this.concreteStrategy = conSortStrategy;
161     }
162     
163     //使用具體的策略(concreteStrategy)對對象進行操作
164     public void sort(List<Student> students)
165     {
166         concreteStrategy.sortStudent(students);
167     }
168 }
View Code

 

5、優缺點

  Strategy模式的優點:   1)Strategy類將具體的演算法進行抽象,為Context類提供了一系列可重用的演算法或行為,同時屏蔽了底層演算法實現的細節,同樣也提高了代碼的可重用性。   2)通過Strategy模式,將具體策略的實現與應用的對象隔離開來,實現行為與對象的解耦;這樣能是應用對象動態便捷的動態改變行為,使得演算法易於切換、易於理解、易於擴展;   3)消除了大量if...else...代碼的冗餘性和複雜性,以行為封裝的形式使代碼的邏輯表達更為清晰。     Strategy模式的缺點:   1)客戶端必須知道所有的策略類,並自行決定使用哪一個策略類:  模式的潛在缺點就是一個客戶要選擇一個合適的Strategy就必須知道這些Strategy到底有何不同。此時可能不得不向客戶暴露具體的實現問題。   2)Strategy和Context之間的通信開銷 :無論各個ConcreteStrategy實現的演算法是簡單還是複雜, 它們都共用Strategy定義的介面。因此很可能某些 ConcreteStrategy不會都用到所有通過這個介面傳遞給它們的信息;簡單的 ConcreteStrategy可能不使用其中的任何信息!這就意味著有時Context會創建和初始化一些永遠不會用到的參數。   3)策略模式將造成產生很多策略類:可以通過使用享元模式在一定程度上減少對象的數量。 增加了對象的數目 Strategy增加了一個應用中的對象的數目。  

6、總結分析

  1)策略模式是一個比較容易理解和使用的設計模式,策略模式是對演算法的封裝,它把演算法的實現和演算法的使用對象解耦,委派給不同的對象管理。策略模式通常把一個系列的演算法封裝到一系列的策略類裡面,作為一個抽象策略類的子類。用一句話來說,就是“準備一組演算法,並將每一個演算法封裝起來,使得它們可以互換”。   2)策略模式僅僅封裝演算法,提供新演算法插入到已有系統中,以及老演算法從系統中“換代”和“退休”的方便。   3)在策略模式中,策略模式並不決定在何時使用何種演算法,演算法的選擇由客戶端來決定。這在一定程度上提高了系統的靈活性,但是客戶端需要理解所有具體策略類之間的區別,以便選擇合適的演算法,這也是策略模式的缺點之一,在一定程度上增加了客戶端的使用難度。          

作者:vincentzh

出處:http://www.cnblogs.com/vincentzh/ 

本文以學習、研究和分享為主,如需轉載,請聯繫本人,標明作者和出處,非商業用途! 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在 servlet 3.0 開始web項目可以完全不需要web.xml配置文件了,所以本文的配置只在支持servlet 3.0及以上的web容器中有效 使用的是spring mvc (4.3.2.RELEASE) + thymeleaf(3.0.2.RELEASE), 持久層使用的 spring的 ...
  • 【Python練習題 017】 兩個乒乓球隊進行比賽,各出三人。甲隊為a,b,c三人,乙隊為x,y,z三人。已抽簽決定比賽名單。有人向隊員打聽比賽的名單。a說他不和x比,c說他不和x,z比。請編程式找出三隊賽手的名單。 這題真真想破我腦袋了,看了好幾份別人的代碼才勉強看懂,真是…… 一開始我只想著先 ...
  • ************************** ...
  • 上周開始試著來用appium,首先開始去官網看,然後下載appium客戶端,下載安裝後,然後筆者開始安裝android sdk ,進官網下載後,筆者下載安裝後,在更新下載SDK Manager的時候一直出錯,下載不下來,翻牆也不行,來到蟲師博客 ,看到方式後,就試著去做,可是按照蟲師的方式還是不行, ...
  • 首先,我們準備文件 jdbc.properties,用於保存連接資料庫的信息,利於我們在配置文件中的使用 一:Spring框架內置的連接池(內置jar包可以使用) 當然,它是使用到 spring-jdbc-4.2.0.RELEASE.jar 在applicationContext.xml(Sprin ...
  • spring 註解多選擇是好事嘛? Spring 經過十多年的快速發展和更新,以其獨特的創新帶來了大量的擁躉者,在選擇方面還帶來了更多選擇!譬如spring bean的裝配(在XML中進行顯式配置、在Java中進行顯式配置、隱式的bean發現機制和自動裝配),註解的多元化(基本註解、jsr250、j ...
  • Spring介紹: spring 使用基本的 JavaBean 來完成以前只可能由 EJB 完成的事情。然而, Spring的用途不僅限於伺服器端的開發。從簡單性、可測試性和松耦合的角度而言,任何Java 應用都可以從 Spring 中受益。 簡單來說, Spring 是一個輕量級的控制反轉(IoC ...
  • 【Python練習題 016】 猴子吃桃問題:猴子第一天摘下若幹個桃子,當即吃了一半,還不癮,又多吃了一個。第二天早上又將剩下的桃子吃掉一半,又多吃了一個。以後每天早上都吃了前一天剩下的一半零一個。到第10天早上想再吃時,見只剩下一個桃子了。求第一天共摘了多少。 這題得倒著推。第10天還沒吃,就剩1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...