久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1576|回復: 0
打印 上一主題 下一主題
收起左側(cè)

設計模式之策略模式——Strategy Pattern

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:107189 發(fā)表于 2016-3-5 23:45 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
*
策略設計模式隸屬行為模式,行為模式關注于算法和算法間的通訊。策略是在給定輸入條件下,實現(xiàn)某個目標的計劃或方案。策略與算法類似,算法是定義好的過程,由多個操作組成,操作可分散實現(xiàn)于不同的類中,我們需要管理和維護這些類。行為模式捕捉操作在類間的劃分方式,并優(yōu)化如何處理其通訊。策略是一個計劃,它也涉及從一組輸入獲得一組輸出。通常,與算法相比策略是更大范圍的可選方案,策略通常代表一組或一簇可以相互替換的方案。(通常情況下可認為其同義),策略也可以是被使用的數(shù)據(jù)。
當有多個可用的策略時,會存在一個策略選擇的問題。當你把策略看成到達目的地的道路時,策略選擇就像一個路由器了,它內(nèi)部封裝路由算法(策略選擇邏輯,一般策略的選擇會有一個依據(jù),比如根據(jù)上下文環(huán)境(自身的或外部的),或是隨機選擇一個)。
*
**
意圖:
策略模式的意圖在于,從算法的宿主(host)類中,將算法分離出來放到一個獨立的類里。對于一個問題的解決可能有若干個算法(策略)可行。如果算法保留在宿主類中,會產(chǎn)生一些混亂的條件語句(路由選擇)。策略模式允許客戶端(client)從一個算法族中選擇一個算法并給其一個簡單的方式去訪問它。這些被分離出來的算法會實現(xiàn)一個共同的操作(操作定義于接口中)。策略操作定義了策略的輸入與輸出,策略實現(xiàn)的工作會留給各個類,這些類以不同的方案實現(xiàn)同一操作,他為宿主類提供了統(tǒng)一的接口,因而這些類是可替換的。這符合類原理類的原理中的: 依賴性倒置和Liskov替代原理。
**
***
應用策略模式的例子。
經(jīng)典的策略模式例子就是排序算法。有很多的排序算法,如冒泡,歸并(java集合排序用此算法),快速,線性排序,shell排序等。這些算法在特定情形下其中的一些會比另一些更“合適”,在時空性價比上更好些。這些算法的輸入都是一樣的(亂序或有序集合)輸出也是一樣的(已排序的集合)。但其內(nèi)部實現(xiàn)不同,在什么條件下選擇那個算法就是一個策略選擇問題。每個算法都有相同的操作如:Collection Sort(Collection SomeArray);
關于排序算法請參考數(shù)據(jù)結(jié)構(gòu)方面的書籍或資料。
***
****
模式圖示(點擊看大圖):

在給定上下文中,合適的策略會從可用的策略簇中選出。
策略的角色:
1.上下文(context):一個對策略將要工作其中的上下文(即環(huán)境)信息的維護者。(Host類)
2.策略接口(IStrategy):為所有的策略定義公共的操作接口。
3.具體策略(concreteStratety):實現(xiàn)策略接口中的操作,該類含有具體的算法。
****
*****
所有的設計模式中的類圖都是角色。我們不必拘泥于其名稱,其中的方法簽名也是可改變的,在我們的環(huán)境中我們需要一些指派(assignment),由我們自定義的類來承擔那些角色。
以下給出一個該模式實現(xiàn)的示例:
描述:有一個人“小明”或是“小王”它們將去旅游,由于資金的問題,他們會選擇不同的交通工具;
第一種Person版本中會根據(jù)自己擁有的錢來選擇不同的旅游策略:坐飛機,坐高客,或是坐火車。
使用策略模式后。將旅游的策略部分提到Person外部,僅讓Person依賴一個抽象的交通工具(IVehicle)現(xiàn)在
Person中的Travel方法僅調(diào)用IVehicle的TravelTo方法。至于具體交通工具的決策邏輯已經(jīng)提到Person類外了。
來看我的練習代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StrategyPatternDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("<<--start 策略模式示例...."+'\n');
            //********測試*******************************************************************
            Test1();
            Test2();
            //********測試*******************************************************************
            System.Console.WriteLine();
            System.Console.WriteLine(" 策略模式示例....--end>>");
            System.Console.ReadLine();
        }
        static void Test1() {
            //不使用策略設計模式的示例
            Person p = new Person();
            p.Name = "小明";
            p.Money = 1500;
            System.Console.WriteLine("{0}有{1}元",p.Name ,p.Money );
            p.Travel("北京");
        }
        static void Test2() {
            System.Console.WriteLine();
            System.Console.WriteLine("<<--startTest2: 重構(gòu)為策略模式后");
            Person_V1 p = new Person_V1();
            p.Name = "小王";
            p.Money = 900;
            IVehicle decisionVehicle;
            if (p.Money >= 2000) {
                decisionVehicle = new Airliner();
            }
            else if (p.Money >= 1000)
            {
                decisionVehicle = new Coach();
            }
            else {
                decisionVehicle = new Train();
            }
            p.RecommendedTravelBy(decisionVehicle);
            System.Console.WriteLine("{0}有{1}元",p.Name ,p.Money );
            p.Travel("上海");
            System.Console.WriteLine(" 重構(gòu)為策略模式后 endTest2-->>");
        }
    }
//*****************原始類********************************************************************
    class Person{
        private string name;
        private double money;
        public Person() {
            this.name = "[SomePerson]";
            this.money = 0.0D;
        }
        public string Name {
            set { this.name = value; }
            get { return this.name; }
        }
        public double Money {
            set { this.money = value; }
            get { return this.money; }
        }
        public void Travel(string where) {
            if (money >= 2000) {
                this.TravelByairliner(where);
            }
            else if (money >= 1000)
            {//暗含邏輯小于2000
                this.TravelByCoach(where );
            }
            else {
                this.TravelByTrain(where );
            }
        }
        #region TravelBySomeVehicle
        private void TravelByairliner(string toSomewhere)
        {
            System.Console.WriteLine("坐飛機去{0} ", toSomewhere);
        }
        private void TravelByTrain(string toSomewhere)
        {
            System.Console.WriteLine("坐火車去{0}", toSomewhere);
        }
        private void TravelByCoach(string toSomewhere)
        {
            System.Console.WriteLine("坐高客去{0} ", toSomewhere);
        }
        #endregion
    }
    //*****************原始類********************************************************************
    //*****************重構(gòu)后********************************************************************
    class Person_V1
    {
        private string name;
        private double money;
        public Person_V1()
        {
            this.name = "[SomePerson]";
            this.money = 0.0D;
        }
        public string Name
        {
            set { this.name = value; }
            get { return this.name; }
        }
        public double Money
        {
            set { this.money = value; }
            get { return this.money; }
        }
        //*********策略對象可由外部傳入*************************************
        private IVehicle vehicle;//某交通工具
        public void RecommendedTravelBy(IVehicle someVehicle){
            this.vehicle = someVehicle;//交通工具由外部決定
         }
        //*********策略對象可由外部傳入*************************************
        public void Travel(string where)
        {
            if (this.vehicle == null)
            {
                System.Console.WriteLine("并未指定交通工具!");
            }
            else
            {
                this.vehicle.TravelTo(where);
            }
        }
      
    }
    #region IStrategy_Interface   策略接口
    public interface IVehicle {
        //策略接口,定義了一個操作TravelTo
        void TravelTo(string where);
    }
    #endregion
   
    #region ConcreteStrategy_Classes 策略實現(xiàn)者類
   
    public class Airliner : IVehicle {
        #region IVehicle 成員
        public void TravelTo(string where)
        {
            //對操作TravelTo的實現(xiàn)
            System.Console.WriteLine("坐飛機去{0} ", where);
        }
        #endregion
    }
    public class Train : IVehicle {

        #region IVehicle 成員
        public void TravelTo(string where)
        {
            System.Console.WriteLine("坐火車去{0}", where);
        }
        #endregion
    }

    public class Coach : IVehicle {

        #region IVehicle 成員
        public void TravelTo(string where)
        {
            System.Console.WriteLine("坐高客去{0} ", where);
        }
        #endregion
    }
    #endregion
    //******************重構(gòu)后*******************************************************************
}
上面策略模式的應用為我們帶來的好處:Person類不再親自決定到底使用那種交通工具了,策略選擇邏輯已被分離出去了,任何實現(xiàn)策略接口的具體類現(xiàn)在都可被傳入到Person類中。這樣體現(xiàn)了可擴展性。Person類只執(zhí)行策略就可以了。
就向這樣的情形。一個企業(yè)中,高層指定戰(zhàn)略計劃,中層負責執(zhí)行戰(zhàn)略,中層不需要選擇戰(zhàn)略計劃塔們只知道執(zhí)行計劃,決策邏輯交給高層去吧!
*****
******
策略設計模式的UML圖示很簡單,它們只是角色示意而已,到底誰來實現(xiàn)這個角色,模式并沒有明說,我們其實也可以將決策邏輯仍放在策略執(zhí)行者之內(nèi)(這里就是指Person類,),它甚至可有一個策略列表,用來存放可用的策略,如果你在提供增加,刪除,或替換策略的公共接口方法,那就更帥了!
策略模式的圖示,與狀態(tài)模式的結(jié)構(gòu)是一樣的,它們都符合類原理:依賴抽象。
但與策略模式不同的是。狀態(tài)模式中存在對象的狀態(tài)轉(zhuǎn)移,它是對狀態(tài)機的建模。
在本例中,Person有一個屬性Money,它也可以表示Person當下的狀態(tài),但是執(zhí)行某個操作后我們后續(xù)并沒有改變它的狀態(tài)(比如說,讓他的錢財減少)。因為策略的選擇總是有些依據(jù)的,這里就依賴了Person內(nèi)部的狀態(tài),但是我們還可以依賴外部的狀態(tài)或環(huán)境(就是角色中的那個Context上下文)。狀態(tài)模式中,操作的具體行為總是依賴系統(tǒng)內(nèi)部的具體狀態(tài)對象,操作完備后必要時還需要置換當前的狀態(tài)對象。但無論如何它們都能改善我們的設計,我們需認真選擇什么環(huán)境下使用那個模式。
另外提一點,《重構(gòu)》一書提到,如果代碼中出現(xiàn)了過多的選擇語句,IF..if else..if...else。Switch(){case:case:case:....}。在面向?qū)ο笳Z境下都是代碼壞味道的體現(xiàn),這些結(jié)構(gòu)典型的屬于面向過程的編程方式,在面向?qū)ο笾卸寄苡枚鄳B(tài)去除。我們上面的示例中仍然有這樣的結(jié)構(gòu),有興趣的朋友可以試試想法去掉它們。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人国产午夜在线观看 | 亚洲视频在线一区 | 国产精品视频偷伦精品视频 | 国产精品片 | 中国黄色毛片视频 | 爱爱无遮挡 | 国产精品国产精品国产专区不片 | 又黑又粗又长的欧美一区 | 在线一区 | 国色天香成人网 | 91大神在线看 | av电影手机在线看 | 美女久久久 | 秋霞电影一区二区三区 | 国产精品一区在线 | 欧美a级成人淫片免费看 | 国产午夜精品久久久久 | 国产91色在线 | 亚洲 | 国产精品国产精品国产专区不卡 | 自拍偷拍亚洲欧美 | 亚洲欧美一区二区三区国产精品 | 天天干天天操天天看 | 羞羞在线视频 | 看一级毛片 | 国产精品一区二区三区久久 | 久久精品免费一区二区三 | 在线观看日韩精品视频 | 91色视频在线 | 一级一级毛片免费看 | 免费成人高清在线视频 | 日韩成人在线一区 | 国产天天操 | 做a网站 | 91精品国产91久久久久久不卞 | 成人免费视频网站 | 久久99视频这里只有精品 | 国户精品久久久久久久久久久不卡 | 亚洲一区 中文字幕 | 欧美精品久久 | 韩日一区二区 | 国产精品视频在线观看 |