欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

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

設(shè)計(jì)模式之策略模式——Strategy Pattern

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

在給定上下文中,合適的策略會(huì)從可用的策略簇中選出。
策略的角色:
1.上下文(context):一個(gè)對(duì)策略將要工作其中的上下文(即環(huán)境)信息的維護(hù)者。(Host類)
2.策略接口(IStrategy):為所有的策略定義公共的操作接口。
3.具體策略(concreteStratety):實(shí)現(xiàn)策略接口中的操作,該類含有具體的算法。
****
*****
所有的設(shè)計(jì)模式中的類圖都是角色。我們不必拘泥于其名稱,其中的方法簽名也是可改變的,在我們的環(huán)境中我們需要一些指派(assignment),由我們自定義的類來承擔(dān)那些角色。
以下給出一個(gè)該模式實(shí)現(xiàn)的示例:
描述:有一個(gè)人“小明”或是“小王”它們將去旅游,由于資金的問題,他們會(huì)選擇不同的交通工具;
第一種Person版本中會(huì)根據(jù)自己擁有的錢來選擇不同的旅游策略:坐飛機(jī),坐高客,或是坐火車。
使用策略模式后。將旅游的策略部分提到Person外部,僅讓Person依賴一個(gè)抽象的交通工具(IVehicle)現(xiàn)在
Person中的Travel方法僅調(diào)用IVehicle的TravelTo方法。至于具體交通工具的決策邏輯已經(jīng)提到Person類外了。
來看我的練習(xí)代碼:
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');
            //********測(cè)試*******************************************************************
            Test1();
            Test2();
            //********測(cè)試*******************************************************************
            System.Console.WriteLine();
            System.Console.WriteLine(" 策略模式示例....--end>>");
            System.Console.ReadLine();
        }
        static void Test1() {
            //不使用策略設(shè)計(jì)模式的示例
            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("坐飛機(jī)去{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; }
        }
        //*********策略對(duì)象可由外部傳入*************************************
        private IVehicle vehicle;//某交通工具
        public void RecommendedTravelBy(IVehicle someVehicle){
            this.vehicle = someVehicle;//交通工具由外部決定
         }
        //*********策略對(duì)象可由外部傳入*************************************
        public void Travel(string where)
        {
            if (this.vehicle == null)
            {
                System.Console.WriteLine("并未指定交通工具!");
            }
            else
            {
                this.vehicle.TravelTo(where);
            }
        }
      
    }
    #region IStrategy_Interface   策略接口
    public interface IVehicle {
        //策略接口,定義了一個(gè)操作TravelTo
        void TravelTo(string where);
    }
    #endregion
   
    #region ConcreteStrategy_Classes 策略實(shí)現(xiàn)者類
   
    public class Airliner : IVehicle {
        #region IVehicle 成員
        public void TravelTo(string where)
        {
            //對(duì)操作TravelTo的實(shí)現(xiàn)
            System.Console.WriteLine("坐飛機(jī)去{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)后*******************************************************************
}
上面策略模式的應(yīng)用為我們帶來的好處:Person類不再親自決定到底使用那種交通工具了,策略選擇邏輯已被分離出去了,任何實(shí)現(xiàn)策略接口的具體類現(xiàn)在都可被傳入到Person類中。這樣體現(xiàn)了可擴(kuò)展性。Person類只執(zhí)行策略就可以了。
就向這樣的情形。一個(gè)企業(yè)中,高層指定戰(zhàn)略計(jì)劃,中層負(fù)責(zé)執(zhí)行戰(zhàn)略,中層不需要選擇戰(zhàn)略計(jì)劃塔們只知道執(zhí)行計(jì)劃,決策邏輯交給高層去吧!
*****
******
策略設(shè)計(jì)模式的UML圖示很簡(jiǎn)單,它們只是角色示意而已,到底誰來實(shí)現(xiàn)這個(gè)角色,模式并沒有明說,我們其實(shí)也可以將決策邏輯仍放在策略執(zhí)行者之內(nèi)(這里就是指Person類,),它甚至可有一個(gè)策略列表,用來存放可用的策略,如果你在提供增加,刪除,或替換策略的公共接口方法,那就更帥了!
策略模式的圖示,與狀態(tài)模式的結(jié)構(gòu)是一樣的,它們都符合類原理:依賴抽象。
但與策略模式不同的是。狀態(tài)模式中存在對(duì)象的狀態(tài)轉(zhuǎn)移,它是對(duì)狀態(tài)機(jī)的建模。
在本例中,Person有一個(gè)屬性Money,它也可以表示Person當(dāng)下的狀態(tài),但是執(zhí)行某個(gè)操作后我們后續(xù)并沒有改變它的狀態(tài)(比如說,讓他的錢財(cái)減少)。因?yàn)椴呗缘倪x擇總是有些依據(jù)的,這里就依賴了Person內(nèi)部的狀態(tài),但是我們還可以依賴外部的狀態(tài)或環(huán)境(就是角色中的那個(gè)Context上下文)。狀態(tài)模式中,操作的具體行為總是依賴系統(tǒng)內(nèi)部的具體狀態(tài)對(duì)象,操作完備后必要時(shí)還需要置換當(dāng)前的狀態(tài)對(duì)象。但無論如何它們都能改善我們的設(shè)計(jì),我們需認(rèn)真選擇什么環(huán)境下使用那個(gè)模式。
另外提一點(diǎ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空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表