策略模式

什么是策略模式?

先看栗子!!!
假設(shè)有一個(gè)抽象超類Duck ,其代碼如下;
<pre>
public abstract class Duck {
public void Quack(){
System.out.println("--Duck speark--");
}
public abstract void display();
public void swim(){
System.out.println("--Duck swim--");
}
}
</pre>
假設(shè)其有一個(gè)GreenDuck子類,代碼如下:
<pre>
public class GreenDuck extends Duck {
public void display() {
System.out.println("****鴨子頭發(fā)色是綠色****");
}
}
</pre>

實(shí)例化對(duì)象

<pre>
public static void main(String[] args) {
GreenDuck gd=new GreenDuck();
RedDuck rd=new RedDuck();
//綠頭鴨
gd.display();
gd.Quack();
gd.swim();
//紅頭鴨
rd.display();
rd.Quack();
rd.swim();
}
</pre>

運(yùn)行結(jié)果
<pre>
****鴨子頭發(fā)色是綠色的****
--Duck speark--
--Duck swim--
****鴨子頭發(fā)色是紅色的****
--Duck speark--
--Duck swim--
</pre>
以上使用了繼承的方法,實(shí)現(xiàn)了代碼的復(fù)用性。使得子類中代碼更簡(jiǎn)潔。但是一項(xiàng)新的問(wèn)題隨之而來(lái)。
假設(shè)超類中擴(kuò)展了一個(gè)新的需求,例如:
<pre>
public abstract class Duck{
...;
public void fly(){
System.out.println("--Duck fly--");
}
}
</pre>
但是超類中的這個(gè)fly()方法不一定是其他子類所需要的。

雖然可以使用面向?qū)ο?OO)的思維,通過(guò)覆蓋父類方法解決繼承的問(wèn)題,代碼如下:
<pre>
public class GreenHeadDuck extend Duck{
...
public void fly(){
System.out.println("~GreenHeadDuck no fly~");
}
}
</pre>
又假設(shè)新出現(xiàn)一個(gè)新的子類Toy_Duck(玩具鴨),這個(gè)子類不會(huì)父類的fly(),Quack()方法,則在Toy_Duck中又要覆蓋相應(yīng)的方法。因此,子類都要從繼承父類中的方法中進(jìn)行篩選有用的功能(又稱覆蓋父類相應(yīng)方法),增加了子類的工作量,可得出復(fù)雜度O(N^2)。

為了應(yīng)對(duì)項(xiàng)目的擴(kuò)展,重新考慮設(shè)計(jì)方式,避免改動(dòng)源碼,降低復(fù)雜度

1)分析項(xiàng)目變化與不變部分,提取變化部分,抽象成接口+實(shí)現(xiàn);
2)鴨子哪些功能是會(huì)根據(jù)新需求變化的?叫聲、飛行..

1、接口:
<pre>
//飛行接口
1) public interface FlyBehavior
{
void fly();
}
//叫聲接口
2)public interface QuackBehavior
{
void quack();
}
</pre>
好處:新增行為簡(jiǎn)單,行為類更好的復(fù)用,組合更方便。既有繼承帶來(lái)的復(fù)用好處,沒(méi)有挖坑

上述接口的實(shí)現(xiàn)類有GoodFlyBehavior、BadFlyBehavior、NoFlyBehavior和GoodQuackBehavior、 BadQuackBehavior、NoQuackBehavior
飛行行為對(duì)象族代碼如下:

<pre>

//GoodFlyBehavior行為對(duì)象
public class GoodFlyBehavior implements FlyBehavior {
public void fly() {
System.out.println("--GoodFly--");
}
}

//BadFlyBehavior行為對(duì)象
public class BadFlyBehavior implements FlyBehavior {
public void fly() {
System.out.println("--BadFly--");
}
}

//NoFlyBehavior行為對(duì)象
public class NoFlyBehavior implements FlyBehavior {
public void fly() {
System.out.println("--不會(huì)飛--");
}
}

</pre>
叫聲行為對(duì)象族代碼如下:
<pre>
//GoodQuackBehavior行為對(duì)象
public class GoodQuackBehavior implements QuackBehavior {
public void quack() {
System.out.println("好聽的叫聲");
}
}
//BadQuackBehavior行為對(duì)象
public class BadQuackBehavior implements QuackBehavior {
public void quack() {
System.out.println("難聽的叫聲" );
}
}
//NoQuackBehavior行為對(duì)象
public class NoQuackBehavior implements QuackBehavior {
public void quack() {
System.out.println(" 不會(huì)叫");
}
}
//
</pre>
重新設(shè)計(jì)模擬鴨子項(xiàng)目:
<pre>public abstract class Duck {
//將飛行、叫聲行為方法定義為對(duì)象。
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
//空構(gòu)造方法
public Duck(){
}
public void Fly(){
flyBehavior.fly();
}
public void Quack(){
quackBehavior.quack();
}
abstract void display();
//設(shè)置叫聲行為對(duì)象接口,便于類方法的組合
public void SetQuackBehavoir(QuackBehavior qb) {
quackBehavior = qb;
}
//設(shè)置飛行行為對(duì)象接口,便于類方法的組合
public void SetFlyBehavoir(FlyBehavior fb) {
flyBehavior = fb;
}
public void swim() {
System.out.println("swimming");
}
}
</pre>
Duck子類GreenHeadDuck代碼如下:
<pre>
public class GreenHeadDuck extends Duck {
public GreenHeadDuck(){
flyBehavior = new GoodFlyBehavior();
quackBehavior = new GoodQuackBehavior();
}
void display() {
System.out.println("GreenHead(綠頭鴨子)");
}
}
</pre>
Duck子類 RedHeadDuck代碼如下:
<pre>
public class RedHeadDuck extends Duck {
public RedHeadDuck() {
flyBehavior = new BadFlyBehavior();
quackBehavior = new BadQuackBehavior();
}
void display() {
System.out.println("RedHead(紅頭鴨子)");
}
}
</pre>
于是我們創(chuàng)建一個(gè)類去檢驗(yàn)以上代碼的可行性。
<pre>
public class TestDemo {
public static void main(String[] args) {
Duck mGreenHeadDuck = new GreenHeadDuck();
Duck mRedHeadDuck = new RedHeadDuck();
//對(duì)象的屬性和方法
mGreenHeadDuck.display();
mGreenHeadDuck.Fly();
mGreenHeadDuck.Quack();
mGreenHeadDuck.swim();
System.out.println("---------分割線----------");
mRedHeadDuck.display();
mRedHeadDuck.Fly();
mRedHeadDuck.Quack();
mRedHeadDuck.swim();
mRedHeadDuck.display();
System.out.println("---------分割線----------");
//可以根據(jù)子類自身屬性設(shè)置相應(yīng)的參數(shù),解決了因繼承帶來(lái)的某些問(wèn)題。
mRedHeadDuck.SetFlyBehavoir(new NoFlyBehavior());
mRedHeadDuck.display();
mRedHeadDuck.Fly();
mRedHeadDuck.SetQuackBehavoir(new NoQuackBehavior());
mRedHeadDuck.Quack();
System.out.println("---------分割線----------");
mGreenHeadDuck.SetFlyBehavoir(new BadFlyBehavior());
mGreenHeadDuck.display();
mGreenHeadDuck.Fly();
mGreenHeadDuck.SetQuackBehavoir(new NoQuackBehavior());
mGreenHeadDuck.Quack();
}
}
</pre>
運(yùn)行結(jié)果:
<pre>
GreenHead(綠頭鴨子)
--GoodFly--
好聽的叫聲
im swim
---------分割線----------
RedHead(紅頭鴨子)
--BadFly--
難聽的叫聲
i m swim
RedHead(紅頭鴨子)
---------分割線----------
RedHead(紅頭鴨子)
--不會(huì)飛--
不會(huì)叫
---------分割線----------
GreenHead(綠頭鴨子)
--BadFly--
不會(huì)叫
</pre>

總結(jié):

策略模式:將類中的行為抽離成接口,實(shí)現(xiàn)相應(yīng)的算法族,在超類里放置行為接口對(duì)象,并提供設(shè)置接口,提高行為組合能力,在子類中具體設(shè)定行為對(duì)象。原則就是:分離變化部分,封裝接口,基于接口編程各種功能。此模式讓行為算法的變化獨(dú)立于算法的使用者。

注意點(diǎn):

策略模式的思想注意點(diǎn)在于:
(1、分析項(xiàng)目中變化部分與不變部分
(2、多用組合少用繼承;用行為類組合,而不是行為的繼承。更有彈性
(3、設(shè)計(jì)模式有沒(méi)有相應(yīng)的庫(kù)直接使用?有些庫(kù)或框架本身就用某種設(shè)計(jì)模式設(shè)計(jì)的
(4、如果找不到適用的模式怎么辦

附言

作為一個(gè)Java程序員,在開發(fā)中遇到的問(wèn)題,多使用面向?qū)ο?,基本原則,抽象設(shè)計(jì)超類繼承的做法去解決。如果還不能解決?那就自己看著吧!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 場(chǎng)景問(wèn)題# 1.1 報(bào)價(jià)管理## 向客戶報(bào)價(jià),對(duì)于銷售部門的人來(lái)講,這是一個(gè)非常重大、非常復(fù)雜的問(wèn)題,對(duì)不同的...
    七寸知架構(gòu)閱讀 5,249評(píng)論 9 62
  • 1 場(chǎng)景問(wèn)題 1.1 報(bào)價(jià)管理 向客戶報(bào)價(jià),對(duì)于銷售部門的人來(lái)講,這是一個(gè)非常重大、非常復(fù)雜的問(wèn)題,對(duì)不同的客戶要...
    4e70992f13e7閱讀 3,216評(píng)論 2 16
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,081評(píng)論 1 15
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是策略模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 策略模式和模板方法模式的區(qū)別 優(yōu)點(diǎn)和...
    w1992wishes閱讀 958評(píng)論 1 7
  • 《嗨,陌生的親們》 忙碌了一天,打個(gè)滴滴,下車前,司機(jī)提醒我,記得給他五星好評(píng)?!昂玫摹!?滿口答應(yīng)。一...
    純?cè)浦逻h(yuǎn)閱讀 190評(píng)論 0 0

友情鏈接更多精彩內(nèi)容