iT邦幫忙

2022 iThome 鐵人賽

DAY 4
0

第二個原則

接續昨天的問題,我們要來看如何更彈性的設計出這個架構!
那要怎麼應用呢?書本提到了第二個原則:

針對"介面"而非"實作"寫程式

為了要讓程式更靈活,我們把行為放在 "介面" 中,而不在鴨子類別中實作細節,這樣就不會把實作綁死在類別裡,例如飛行的實作:(以下皆由C++改寫原書內JAVA程式)

class FlyBehavior // interface of fly
{
    public:
        virtual void fly()=0;
};

class FlyInSky: public FlyBehavior
{
    public:
        void fly() override
        {
            cout << "fly in sky!" << endl;
        }
};

class FlyNoWay: public FlyBehavior
{
    public:
        void fly() override
        {
            cout << "cannot fly!" << endl;
        }
};

如此,就可以 動態 的改變行為,如下:

//-----
// before: 寫死實作
MallardDuck mallard;
mallard.fly(); // 鴨子fly()行為無法改變

// after: 善用介面
Duck *mallard = new MallardDuck();
mallard->performFly();
// output: 目前fly行為
mallard->setFlyBefavior(new FlyNoWay()); // 可動態改變行為
mallard->performFly();
// output: FlyNoWay()行為

依照這種方式,我們可以把會變動的這幾種行為設計成這種方式,UML圖如下(依據書本內容以draw.io繪製):
https://ithelp.ithome.com.tw/upload/images/20220918/20140096kZ4VvIwQx7.png

整合行為

有了原本鴨子的類別,也有了告自行為的類別,就可以來將整個結構整合在一起了。
要怎麼將鴨子跟行為串聯在一起呢?我們可以把這兩個行為類別再放到鴨子裡面,例如以下的方式:

class Duck
{
    public:
        FlyBehavior *flyBehavior = nullptr;
        QuackBehavior *quackBehavior = nullptr;

        Duck(){}
        virtual void display()=0;
        void performQuack()
        {
            flyBehavior->fly();
        }
        void performFly()
        {
            quackBehavior->quack();
        }
};

這樣,各式的鴨子行為都可以被各自串聯起來,不會再針對每一類多出來的行為,需要重複地改寫不變的部分了。
而要動態地改變行為,我們可以使用setFlyBehavior()這種函式來設定,如以下:

class Duck
{
    public:
        void setFlyBehavior(FlyBehavior *fb)
        {
		    flyBehavior = fb;
	    }
        void setQuackBehavior(QuackBehavior *qb)
        {
		    quackBehavior = qb;
        }
};

就可以達到前面動態改變的功能。

今日小結

現在知道了FlyBehaviorDuck這兩個類別如何實作,拼起來就可以完成整個架構了;不如自行試試看QuackBehaviorMallardDuck的撰寫,並檢視加上了今天這些內容,昨天想到的UML是否有需要修改的地方,明天繼續來看書本中給出的最終UML架構與第三個原則,將策略模式做收尾!


上一篇
[Day 3] 策略模式 (1)
下一篇
[Day 5] 策略模式 (3)
系列文
設計模式探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言