日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

[设计模式学习笔记] -- 策略模式

發布時間:2024/1/8 asp.net 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [设计模式学习笔记] -- 策略模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

策略模式

定義了算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化獨立于使用算法的客戶。

  舉一個簡單的例子來描述策略模式。

  設計一款冷兵器時代士兵打仗的游戲,游戲內部設計要使用OO技術。

  首先,設計一個士兵對象(Soilder)作為父類,然后在設計許多不同種類的士兵對象來繼承士兵這個父類,比如:長槍兵(Spearman)、騎兵(Cavalryman)、弓箭手(Bowman)等等,設計好后進行討論,覺得不錯沒有問題,可以開始開發,測試,游戲公測……一切都不錯,具體如下面的類圖所示:

  

  在游戲運營了一段時候之后,發現需要一些新元素來吸引玩家,要求不同種類的士兵的攻擊動作不同,并且要求士兵需要有游泳、攀爬等技能。使用OO技術非常好解決啊,打開類的設計圖開始干活吧!可以把hit方法設計成抽象方法,讓每種士兵都實現自己的hit,然后在Soilder類中加入游泳,攀爬的方法,修改的類圖如下:

  

  使用這種設計方式后,在游戲運行的過程中我們會看到,騎兵騎著馬在爬樹。顯然的,在設計的時候忽略了一點,并非所有的士兵都可以游泳和攀爬。有許多不可做這些行為的士兵,對代碼的局部修改,影響的層面可不僅是局部。

  使用繼承如何?

  把swim和clmb放到子類中,覆蓋掉父類的對應方法,像hit的做法一樣。可如果以后要加入其他類型的士兵又會如何?比如重甲步兵沒辦法游泳也沒辦法攀爬,因為重甲太重了,而騎兵則無法騎著馬攀爬,但可以騎著馬過河等等。可見利用繼承來提供士兵的行為會造成:

  1.代碼在多個子類中重復;

  2.運行時的行為不容易改變;

  3.很難知道所有士兵的全部行為;

  4.改變會牽一發而動全身,造成其他某些類型的士兵不想要的行為;

  利用接口如何?

  可以加入ISwin和IClimb接口,把swim函數和climb函數從父類中取出來,并被子類實現,如下圖所示:

  

  但士兵的規格會常常改變,每當有新的士兵類型出現,就要被迫檢查兵可能需要實現ISwim和IClimb接口。并且這么以來重復的代碼會變多,因為實現的可以游泳和爬樹的代碼是一樣的。比如有一天swim的方式發生了變化,現有的50個士兵子類都需要修改swim函數,這是不可以接受的。

  如何解決?

  可以看出,并非所有的子類都會游泳和爬樹,所以繼承并不是適當的解決方式。雖然使用接口可以解決一部分問題,但是卻造成了代碼無法復用,幸運的是,有一個原則恰好用于此處。

設計原則1

找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。

  也就是說,每次需求一來,都會使某些方面的代碼發生變化,那么基本可以確定這部分代碼需要被抽出來和其他穩定的代碼有所區分。

  現在,為了要分開變化和不會變化的部分,我們準備建立兩組類,一個是swim相關的,一個是clmb相關的,并且要做到一切能有彈性,正因為一開始設計的行為沒有彈性才導致種種問題。比方說,我要產生一個新的類型的輕甲士兵,并指定行為攀爬給他,也就是說在士兵類中包涵設置行為的方法,這樣就可以在運行時動態改變行為,有了這些目標要實現,就引出了第二個設計原則。

設計原則2

針對接口或抽象類編程,而不是針對實現編程。

  我們利用接口代表每個行為(Behavior),比方說SwimBehavior和ClimbBehavior,而行為的每個實現都將實現其中的一個接口。Soilder類不會負責實現它們,反而是由一組其他類專門去實現,并整合到Soilder類中,具體的做法是在Soilder類中加入兩個實例變量,分別為SwimBehavior和ClimbBehavior,聲明為接口類型,每個士兵子類都會動態的設置這些變量在運行時引用正確的行為類型。看一下類圖與實現的代碼(Java代碼)。

  

  

package cn.net.bysoft.Strategy;// 士兵 public abstract class Soldier {// 士兵的名字private String name;private SwimBehavior swimBehavior;private ClimbBehavior climbBehavior;public Soldier() {super();}public Soldier(String name) {super();this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public SwimBehavior getSwimBehavior() {return swimBehavior;}public void setSwimBehavior(SwimBehavior swimBehavior) {this.swimBehavior = swimBehavior;}public ClimbBehavior getClimbBehavior() {return climbBehavior;}public void setClimbBehavior(ClimbBehavior climbBehavior) {this.climbBehavior = climbBehavior;}// 顯示士兵的信息public void display() {System.out.println("這個士兵的名字:" + name);}// 士兵攻擊敵人。public abstract void hit();// 委托給行為去處理。public void swim() {swimBehavior.swim();}public void climb() {climbBehavior.climb();} } 士兵類的代碼 package cn.net.bysoft.Strategy;// 長槍兵 public class Spearman extends Soldier {public Spearman() {}public Spearman(String name) {super(name);}@Overridepublic void hit() {// TODO Auto-generated method stubSystem.out.println("士兵使用長槍去攻擊敵人");} }package cn.net.bysoft.Strategy;// 騎兵 public class Cavalryman extends Soldier {public Cavalryman() {}public Cavalryman(String name) {super(name);}@Overridepublic void hit() {// TODO Auto-generated method stubSystem.out.println("騎士在馬上用刀攻擊敵人");} }package cn.net.bysoft.Strategy;// 弓箭手 public class Bowman extends Soldier {public Bowman() {}public Bowman(String name) {super(name);}@Overridepublic void hit() {// TODO Auto-generated method stubSystem.out.println("弓箭手拉弓瞄準射擊敵人");} } 長槍兵、騎士、弓箭手等士兵的代碼 package cn.net.bysoft.Strategy;// 游泳行為的接口。 public interface SwimBehavior {// 只需在此定義一個游泳的行為方法即可。public void swim(); }package cn.net.bysoft.Strategy;// 不能游泳 public class SwimNoWay implements SwimBehavior {public void swim() {// TODO Auto-generated method stubSystem.out.println("這個士兵不能游泳");}}package cn.net.bysoft.Strategy;// 士兵自己游泳,不通過其他途徑。 public class SwimWithBody implements SwimBehavior{public void swim() {// TODO Auto-generated method stubSystem.out.println("士兵自己游泳過河");}}package cn.net.bysoft.Strategy;// 士兵騎馬游泳 public class SwimWithHouse implements SwimBehavior {public void swim() {// TODO Auto-generated method stubSystem.out.println("士兵騎馬過河");}} 游泳行為接口與其實現類的代碼 package cn.net.bysoft.Strategy;// 攀爬行為的接口 public interface ClimbBehavior {public void climb(); }package cn.net.bysoft.Strategy;public class ClimbNoWay implements ClimbBehavior {public void climb() {// TODO Auto-generated method stubSystem.out.println("這個士兵不能攀爬");}}package cn.net.bysoft.Strategy;// 士兵爬樹。 public class ClimbTree implements ClimbBehavior {public void climb() {// TODO Auto-generated method stubSystem.out.println("士兵開始爬樹");}} 攀爬行為接口與其實現類的代碼 package cn.net.bysoft.Strategy;public class Game {public static void main(String[] args) {// TODO Auto-generated method stub// 一個玩家建立一個長矛兵進入游戲Soldier spearman = new Spearman("長矛高手");spearman.hit();// 設置這個士兵的行為,可以自己游泳,爬樹。spearman.setSwimBehavior(new SwimWithBody()); spearman.setClimbBehavior(new ClimbTree());spearman.swim();spearman.climb();System.out.println(" ============================= ");// 另一個玩家建立士兵進入游戲Soldier cavalryman = new Cavalryman("圓桌騎士");cavalryman.hit();// 設置這個士兵的行為,可以騎馬過河,但是不可以爬樹。cavalryman.setSwimBehavior(new SwimWithHouse());cavalryman.setClimbBehavior(new ClimbNoWay());cavalryman.swim();cavalryman.climb();} } 測試類,測試策略模式

  總結一下,請特別注意類之間的關系,關系可以是IS-A(是一個)也可以是HAS-A(有一個)或IMPLEMENTS(實現)。HAS-A關系相當有趣,每一個士兵都有SwimBehavior和ClimbBehavior的行為,并將這些動作交給它們去處理,當將兩個類結合起來使用,就是這種組合。這種做法和繼承不同的地方在于,行為不是繼承來的,而是和適當的行為對象組合來的。這是一個很重要的技巧,騎士是使用了第三個設計原則:

設計原則3

多用組合,少用繼承。

  使用組合建立系統具有很大的彈性,不僅可以將算法族封裝成類,更可以在運行時動態地改變行為,只要組合的行為對象符合正確的接口標準即可。以上就是策略模式的介紹。

轉載于:https://www.cnblogs.com/DeadGardens/p/5132116.html

總結

以上是生活随笔為你收集整理的[设计模式学习笔记] -- 策略模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。