【HeadFirst 设计模式总结】1.策略模式
1.書中舉了一個鴨子類的設計,有些會飛或者會叫,有些不會飛可能也不會叫,用繼承則導致不該有的功能通過繼承而繼承了下來,使用接口則代碼無法做到最大程度的重用。進而引出設計原則1:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起,把會變化的部分取出并封裝起來,好讓其他部分不會受到影響。——每個設計模式背后的精神所在。
2.我們希望運行時動態的改變一些行為,這就引出了第二個原則:針對接口編程,而不是針對實現編程。?因此,鴨子的行為將被放在分開的類——我們可以將其叫做“行為類”中,此類專門提供某行為接口的實現。針對接口編程的意思是針對超類型編程——變量的聲明類型應該是超類,通常是一個抽象類或者一個接口,如此,只要是具體實現此超類型的類所產生的對象,都可以指定給這個變量,這也意味著,聲明類時不用理會以后執行時的真正對象類型。
針對實現編程?
Dog d=new Dog();?
d.dark();?
針對接口編程?
Animal animal=new Dog();?
animal.makesound();?
更好的針對接口編程
a = getAnimal();?
a.makeSound();
不得不針對具體實現coding?
利用animal多態處理?
運行時才指定具體實現的對象
最后設計的樣子是兩個接口,一個飛,一個叫,每個接口中有相應的方法,然后設計不同的類對這個接口進行不同的實現。
然后在超類的設計中,行為變量被聲明為“接口”類型的變量,然后具體動作的方法由接口類型的變量相對應的方法所實現。子類中,構造函數中指明這些接口類型的變量具體對應的是哪一個具體實現。這樣的話,通過一個“接口”類型的變量,靈活性就更高了,雖然此時在構造函數中我們還是引入了具體實現。
3.進一步,我們希望可以自己設定具體的行為而不是在構造函數中寫死,那么我們可以使用setter method,通過向外提供接口來設置從超類那繼承的接口類型的成員變量。
4.最后我們看到的設計局面是:各種鴨子繼承了Duck,飛行行為實現了FlyBehavior接口,呱呱叫行為實現了QuackBehavior接口。設計的基本理念在于行為不是繼承而來的,而是通過適當的行為對象“組合”而來。這個總結就可以歸納出第三個設計原則:多用組合,少用繼承。這樣可使系統更具有彈性。
最后我們來看看這個模式的定義:
策略模式定義了算法簇,分別封裝起來,讓它們之間可以互相替換,此模式讓方法的變化獨立于使用方法的Client,適用于繼承后的動作發生變化,要動態的改變對象的行為時。
核心思想:將is-a 轉換為has-a.
?
?
基本的思路:將一些原先要繼承的方法,以接口的方式抽象出來,然后再以實現該接口的方式定義一些類以完成實際能力的實現;同時在基類中以組合的方式將該接口的實例放入基類,基類同時提供設置這個實例的接口以及這個方法的封裝,子類繼承基類時對這些接口實例進行設置即可。
?
5.TIPs:
1)在開發中使用模式詞匯,但是不要寫一個helloworld都要扯上模式。
2)沒有所謂設計模式庫,只有設計模式條目。
3)模式并不只是利用了OO的設計原則。應用場景中若是沒有合適的模式則使用最基本的OO原則。
附:鴨子的設計
建立不同的鴨子類 fly行為 // 飛行接口 public interface FlyBehavior { public void fly(); } // 飛 public class FlyWithWings implements FlyBehavior{ public void fly() { System.out.println("正在用翅膀飛行"); } } // 不飛 public class FlyNoWay implements FlyBehavior{ public void fly() { System.out.println("不會飛"); } } //坐火箭飛 public class FlyRocketPowered implements FlyBehavior{ public void fly() { System.out.println("坐火箭飛"); } } quack行為 // 叫接口 public interface QuackBehavior { public void quack(); } // 嘎嘎叫 public class Quack implements QuackBehavior. { public void quack() { System.out.println("嘎嘎叫"); } } // 吱吱叫 public class Squeak implements QuackBehavior{ public void quack() { System.out.println("吱吱叫"); } } // 不叫 public class MuteQuack implements QuackBehavior{ public void quack() { System.out.println("不會叫"); } } 實現Duck類 // 鴨子超類 public abstract class Duck { // 默認的行為 FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } public void setFlyBehavior(FlyBehavior. fb) { flyBehavior = fb; } public void setQuackBehavior(QuackBehavior. qb) { quackBehavior = qb; } abstract void display(); public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public void swim() { System.out.println("正在游泳~~"); } } // 野鴨 public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); //這里也可以使用setFlyBehavior方法,下同!} public void display() { System.out.println("綠頭鴨"); } } // 紅頭鴨 public class RedHeadDuck extends Duck { public RedHeadDuck() { flyBehavior = new FlyWithWings(); quackBehavior = new Quack(); } public void display() { System.out.println("紅頭鴨"); } } // 橡皮鴨 public class RubberDuck extends Duck { public RubberDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Squeak(); } public void display() { System.out.println("橡皮鴨"); } } //模型鴨 public class ModelDuck extends Duck { public ModelDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Quack(); } public void display() { System.out.println("模型鴨"); } } 測試代碼:public class MiniDuckSimulator { public static void main(String[] args) { MallardDuck mallard = new MallardDuck(); RubberDuck rubberDuckie = new RubberDuck(); RedHeadDuck redHeadDuck = new RedHeadDuck(); ModelDuck model = new ModelDuck(); mallard.performQuack(); rubberDuckie.performQuack(); redHeadDuck.performQuack(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); } }轉載于:https://www.cnblogs.com/shakin/p/4218503.html
總結
以上是生活随笔為你收集整理的【HeadFirst 设计模式总结】1.策略模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何实现CSS居中?–CSS居中常用方法
- 下一篇: asp.net ajax控件工具集 Au