【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();
}
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com