欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
設計模式之策略模式——Strategy Pattern
[打印本頁]
作者:
51黑tt
時間:
2016-3-5 23:45
標題:
設計模式之策略模式——Strategy Pattern
*
策略設計模式隸屬行為模式,行為模式關注于算法和算法間的通訊。策略是在給定輸入條件下,實現某個目標的計劃或方案。策略與算法類似,算法是定義好的過程,由多個操作組成,操作可分散實現于不同的類中,我們需要管理和維護這些類。行為模式捕捉操作在類間的劃分方式,并優化如何處理其通訊。策略是一個計劃,它也涉及從一組輸入獲得一組輸出。通常,與算法相比策略是更大范圍的可選方案,策略通常代表一組或一簇可以相互替換的方案。(通常情況下可認為其同義),策略也可以是被使用的數據。
當有多個可用的策略時,會存在一個策略選擇的問題。當你把策略看成到達目的地的道路時,策略選擇就像一個路由器了,它內部封裝路由算法(策略選擇邏輯,一般策略的選擇會有一個依據,比如根據上下文環境(自身的或外部的),或是隨機選擇一個)。
*
**
意圖:
策略模式的意圖在于,從算法的宿主(host)類中,將算法分離出來放到一個獨立的類里。對于一個問題的解決可能有若干個算法(策略)可行。如果算法保留在宿主類中,會產生一些混亂的條件語句(路由選擇)。策略模式允許客戶端(client)從一個算法族中選擇一個算法并給其一個簡單的方式去訪問它。這些被分離出來的算法會實現一個共同的操作(操作定義于接口中)。策略操作定義了策略的輸入與輸出,策略實現的工作會留給各個類,這些類以不同的方案實現同一操作,他為宿主類提供了統一的接口,因而這些類是可替換的。這符合類原理類的原理中的: 依賴性倒置和Liskov替代原理。
**
***
應用策略模式的例子。
經典的策略模式例子就是排序算法。有很多的排序算法,如冒泡,歸并(java集合排序用此算法),快速,線性排序,shell排序等。這些算法在特定情形下其中的一些會比另一些更“合適”,在時空性價比上更好些。這些算法的輸入都是一樣的(亂序或有序集合)輸出也是一樣的(已排序的集合)。但其內部實現不同,在什么條件下選擇那個算法就是一個策略選擇問題。每個算法都有相同的操作如:Collection Sort(Collection SomeArray);
關于排序算法請參考數據結構方面的書籍或資料。
***
****
模式圖示(點擊看大圖):
在給定上下文中,合適的策略會從可用的策略簇中選出。
策略的角色:
1.上下文(context):一個對策略將要工作其中的上下文(即環境)信息的維護者。(Host類)
2.策略接口(IStrategy):為所有的策略定義公共的操作接口。
3.具體策略(concreteStratety):實現策略接口中的操作,該類含有具體的算法。
****
*****
所有的設計模式中的類圖都是角色。我們不必拘泥于其名稱,其中的方法簽名也是可改變的,在我們的環境中我們需要一些指派(assignment),由我們自定義的類來承擔那些角色。
以下給出一個該模式實現的示例:
描述:有一個人“小明”或是“小王”它們將去旅游,由于資金的問題,他們會選擇不同的交通工具;
第一種Person版本中會根據自己擁有的錢來選擇不同的旅游策略:坐飛機,坐高客,或是坐火車。
使用策略模式后。將旅游的策略部分提到Person外部,僅讓Person依賴一個抽象的交通工具(IVehicle)現在
Person中的Travel方法僅調用IVehicle的TravelTo方法。至于具體交通工具的決策邏輯已經提到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: 重構為策略模式后");
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(" 重構為策略模式后 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
}
//*****************原始類********************************************************************
//*****************重構后********************************************************************
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 策略實現者類
public class Airliner : IVehicle {
#region IVehicle 成員
public void TravelTo(string where)
{
//對操作TravelTo的實現
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
//******************重構后*******************************************************************
}
上面策略模式的應用為我們帶來的好處:Person類不再親自決定到底使用那種交通工具了,策略選擇邏輯已被分離出去了,任何實現策略接口的具體類現在都可被傳入到Person類中。這樣體現了可擴展性。Person類只執行策略就可以了。
就向這樣的情形。一個企業中,高層指定戰略計劃,中層負責執行戰略,中層不需要選擇戰略計劃塔們只知道執行計劃,決策邏輯交給高層去吧!
*****
******
策略設計模式的UML圖示很簡單,它們只是角色示意而已,到底誰來實現這個角色,模式并沒有明說,我們其實也可以將決策邏輯仍放在策略執行者之內(這里就是指Person類,),它甚至可有一個策略列表,用來存放可用的策略,如果你在提供增加,刪除,或替換策略的公共接口方法,那就更帥了!
策略模式的圖示,與狀態模式的結構是一樣的,它們都符合類原理:依賴抽象。
但與策略模式不同的是。狀態模式中存在對象的狀態轉移,它是對狀態機的建模。
在本例中,Person有一個屬性Money,它也可以表示Person當下的狀態,但是執行某個操作后我們后續并沒有改變它的狀態(比如說,讓他的錢財減少)。因為策略的選擇總是有些依據的,這里就依賴了Person內部的狀態,但是我們還可以依賴外部的狀態或環境(就是角色中的那個Context上下文)。狀態模式中,操作的具體行為總是依賴系統內部的具體狀態對象,操作完備后必要時還需要置換當前的狀態對象。但無論如何它們都能改善我們的設計,我們需認真選擇什么環境下使用那個模式。
另外提一點,《重構》一書提到,如果代碼中出現了過多的選擇語句,IF..if else..if...else。Switch(){case:case:case:....}。在面向對象語境下都是代碼壞味道的體現,這些結構典型的屬于面向過程的編程方式,在面向對象中都能用多態去除。我們上面的示例中仍然有這樣的結構,有興趣的朋友可以試試想法去掉它們。
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1