圖解Java設計模式之策略模式
- 撰寫鴨子專案,具體要求如下 :
- 傳統方案解決鴨子問題的分析和代碼實作
- 傳統方式解決鴨子問題分析和解決方案
- 策略模式基本介紹
- 策略模式的原理類圖
- 策略模式解決鴨子問題
- 策略模式在JDK - Arrays 應用的原始碼分析
- 策略模式的注意實作和細節
撰寫鴨子專案,具體要求如下 :
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)這演算法體現來幾個設計原則,第一、把變化的代碼從不變的代碼中分離出來;第二、針對介面編程而不是具體類(定義來策略介面):第三、多組合/聚合,少用繼承(客戶通過組合方式使用策略),
策略模式的原理類圖

說明 :從上圖可以看到,客戶端context 有成員變數 strategy 或者其它的策略介面,至于需要使用到那個策略,我們可以在構造器中指定,
策略模式解決鴨子問題
1)應用實體要求
撰寫程式完成前面的鴨子專案,要求使用策略模式
2)類圖
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("北京鴨的實際飛翔能力");
}
}
策略模式在JDK - Arrays 應用的原始碼分析

說明:
- 實作了 Comparator 介面(策略介面) , 匿名類 物件 new Comparator(){…}
- 物件 new Comparator(){…} 就是實作了 策略介面 的物件
- public int compare(Integer o1, Integer o2){} 指定具體的處理方式
策略模式的注意實作和細節
1)策略模式的關鍵是 :分析專案中變化部分與不變部分
2)策略模式的核心思想是 :多用組合/聚合,少用繼承;用行為類組合,而不是行為的繼承,更有彈性,
3)體現了“開閉原則”,客戶端增加行為不用修改原有代碼,只要添加一種策略(或者行為)即可,避免了使用多重轉移陳述句(if…else if … else);
4)提供了可以替換繼承關心的辦法 :策略模式將演算法封裝在獨立的Strategy類中使得你可以獨立于其Context改變它,使它易于切換、易于理解、易于擴展,
5)需要注意的是 :每添加一個策略就要增加一個類,當策略過多是會導致類數目龐大,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/16310.html
標籤:設計模式
上一篇:圖解Java設計模式之狀態模式
下一篇:設計模式:單例模式
