1)有各類鴨子(好比 野鴨、北京鴨、水鴨等)鴨子有各類行爲,好比叫、飛行等等。
2)顯示鴨子的信息算法
1)傳統的設計方案(類圖)
編程
package com.example.demo.dtrategy; public abstract class Duck { public Duck() {} // 顯示鴨子信息 public abstract void display(); public void quack() { System.out.println("鴨子嘎嘎叫~~~"); } public void swim() { System.out.println("鴨子會游泳~~~"); } public void fly() { System.out.println("鴨子會飛~~~"); } } package com.example.demo.dtrategy; public class PekingDuck extends Duck { @Override public void display() { // TODO Auto-generated method stub System.out.println("~~ 北京鴨 ~~"); } @Override public void fly() { // TODO Auto-generated method stub System.out.println("北京鴨不能飛翔"); } } package com.example.demo.dtrategy; public class ToyDuck extends Duck { @Override public void display() { // TODO Auto-generated method stub System.out.println("玩具鴨"); } //須要重寫父類的全部方法 public void quack() { System.out.println("玩具鴨不能叫~~"); } public void swim() { System.out.println("玩具鴨不會游泳~~"); } public void fly() { System.out.println("玩具鴨不會飛翔~~~"); } } package com.example.demo.dtrategy; public class WildDuck extends Duck { @Override public void display() { // TODO Auto-generated method stub System.out.println(" 這是野鴨 "); } }
1)其它鴨子,都繼承類Duck類,因此fly讓全部子類都會飛類,這是不正確的。
2)上面說的1的問題,實際上是繼承帶來的問題 :對類的局部改動,尤爲超類的局部改動,會影響其它部分。會有溢出效應。
3)爲了改進1問題,咱們能夠經過覆蓋fly 方法來解決 - 》覆蓋解決
4)問題又來來,若是咱們有一個玩具鴨子ToyDuck,這樣就須要ToyDuck去覆蓋Duck的全部實現的方法 = 》策略模式(strategy pattern)設計模式
1)策略模式(Strategy Pattern)中,定義算法族,分別封裝起來,讓他們之間能夠相互替換,此模式讓算法的變化獨立於使用算法的客戶。
2)這算法體現來幾個設計原則,第1、把變化的代碼從不變的代碼中分離出來;第2、針對接口編程而不是具體類(定義來策略接口):第3、多組合/聚合,少用繼承(客戶經過組合方式使用策略)。ide
說明 :從上圖能夠看到,客戶端context 有成員變量 strategy 或者其它的策略接口,至於須要使用到那個策略,咱們能夠在構造器中指定。源碼分析
1)應用實例要求
編寫程序完成前面的鴨子項目,要求使用策略模式
2)類圖
this
package com.example.demo.dtrategy.improe; public interface FlyBehavior { void fly(); // 子類具體實現 } package com.example.demo.dtrategy.improe; public interface QuackBehavior { } package com.example.demo.dtrategy.improe; public class BadFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println(" 飛翔技術通常 "); } } package com.example.demo.dtrategy.improe; public abstract class Duck { //屬性, 策略接口 FlyBehavior flyBehavior; //其它屬性<->策略接口 QuackBehavior quackBehavior; public Duck() {} // 顯示鴨子信息 public abstract void display(); public void quack() { System.out.println("鴨子嘎嘎叫~~~"); } public void swim() { System.out.println("鴨子會游泳~~~"); } public void fly() { // 改進 if(flyBehavior != null) { flyBehavior.fly(); } } public FlyBehavior getFlyBehavior() { return flyBehavior; } public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public QuackBehavior getQuackBehavior() { return quackBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } } package com.example.demo.dtrategy.improe; public class GoodFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println(" 飛翔技術高超 ~~~"); } } package com.example.demo.dtrategy.improe; public class NoFlyBehavior implements FlyBehavior { @Override public void fly() { // TODO Auto-generated method stub System.out.println(" 不會飛翔 "); } } package com.example.demo.dtrategy.improe; public class PekingDuck extends Duck { //假如北京鴨能夠飛翔,可是飛翔技術通常 public PekingDuck() { // TODO Auto-generated constructor stub flyBehavior = new BadFlyBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println("~~北京鴨~~~"); } } package com.example.demo.dtrategy.improe; public class ToyDuck extends Duck { public ToyDuck() { // TODO Auto-generated constructor stub flyBehavior = new NoFlyBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println("玩具鴨"); } //須要重寫父類的全部方法 public void quack() { System.out.println("玩具鴨不能叫~~"); } public void swim() { System.out.println("玩具鴨不會游泳~~"); } } package com.example.demo.dtrategy.improe; public class WilDuck extends Duck { /** * 構造器,傳入FlyBehavor 的對象 */ public WilDuck() { flyBehavior = new GoodFlyBehavior(); } @Override public void display() { // TODO Auto-generated method stub System.out.println(" 這是野鴨 "); } } package com.example.demo.dtrategy.improe; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub WilDuck wildDuck = new WilDuck(); wildDuck.fly();// ToyDuck toyDuck = new ToyDuck(); toyDuck.fly(); PekingDuck pekingDuck = new PekingDuck(); pekingDuck.fly(); //動態改變某個對象的行爲, 北京鴨 不能飛 pekingDuck.setFlyBehavior(new NoFlyBehavior()); System.out.println("北京鴨的實際飛翔能力"); } }
說明:.net
1)策略模式的關鍵是 :分析項目中變化部分與不變部分
2)策略模式的核心思想是 :多用組合/聚合,少用繼承;用行爲類組合,而不是行爲的繼承。更有彈性。
3)體現了「開閉原則」。客戶端增長行爲不用修改原有代碼,只要添加一種策略(或者行爲)便可,避免了使用多重轉移語句(if…else if … else);
4)提供了能夠替換繼承關心的辦法 :策略模式將算法封裝在獨立的Strategy類中使得你能夠獨立於其Context改變它,使它易於切換、易於理解、易於擴展。
5)須要注意的是 :每添加一個策略就要增長一個類,當策略過可能是會致使類數目龐大。設計