Re: [問題] Strategy/State Pattern in C++

看板C_and_CPP (C/C++)作者 (朴髮箍)時間15年前 (2011/04/23 22:50), 編輯推噓7(705)
留言12則, 3人參與, 最新討論串3/3 (看更多)
※ 引述《iamstudent (stu)》之銘言: 吃掉... : 所以方法變成只有兩種:(如果還有更多,請指教) : 方法a: 大class去friend所有的state子類別 : 方法b: 大class設計好低階的public介面函數,然後抽出去的類別只用這些介面存取 : 問題是這兩個方法感覺都不夠好 : 方法a會有超多的friend敘述 : 而方法b有的時候還真的設計不出來 : OOAD版上有人提供了方法c:把大class的所有成員物件改public : 這個也不是我要的 : 因為等於直接暴露整個內容出去了 : 那麼還有其他方法嗎? 應該由「需求」來決定該使用何種設計模式. 如果兩個 concrete strategies 需要存取到 Context 的屬性, 那 麼存取到的部份一定也相同, 否則他們就不該實作相同的 Strategy 介面. 使用策略模式, 有時是為了讓客戶端能夠輕易擴充自己的程式, 讓 他們選擇性的實作某種Strategy. 這時候就不該考慮完全曝露的方 法(甚至也破壞了抽象化能力), 或是加上新的 friend. 綜合以上建議, 我覺得你要了解: 1.需要存取的理由 2.開放之後帶來的風險 3.如何提供合適的介面(其實以屬性為單位的 setter/getter 也不少見) 介面難想通常是需求、責任不明確使然, 雖說要套用策略模式到你 的架構也不無可能, 以下是我的作法: // 對應到你本來很大的 class class Context { friend class FullyAccessor; int first, second, third; // Strategy 介面指標s... public: // 其他介面 }; // 實作者內部使用的類別, 預設擁有最大權限 class FullyAccessor { // ... public: FullyAccessor( Context* ); int getFirst(); void setFirst( int ); int getSecond(); void setSecond( int ); int getThird(); void setThird( int ); }; 你可能有一種策略需要存取 Context 全部屬性, 則需要繼承(視情 況開放部分介面): class UseAllAttributes : private FullyAccessor { public: UseAllAttributes( Context* ); protected: using FullyAccessor::getFirst; using FullyAccessor::setFirst; using FullyAccessor::getSecond; using FullyAccessor::setSecond; using FullyAccessor::getThird; using FullyAccessor::setThird; }; 只存取部份屬性則繼承: class UseFirstOnly : private FullyAccessor { public: UseFirstOnly( Context* ); protected: using FullyAccessor::getFirst; using FullyAccessor::setFirst; }; 然後策略的介面像是這樣: class Strategy : public UseFirstOnly { public: Strategy( Context* ); virtual void act() = 0; }; // 客戶端程式碼 class ConcreteStrategy : public Strategy { public: ConcreteStrategy( Context* ); virtual void act() { cout << getFirst() << endl; cout << getSecond() << endl; // compile error } }; 其他用法依此類推. 補上類別圖: ┌────┐ ┌───────┐ │ Context│←──◇│ FullyAccessor│ └────┘ └───────┘ ┌───┴───┐ ┌────┴──┐ ┌──┴─────┐ │ UseFirstOnly │ │UseAllAttributes│ └───────┘ └────────┘ │ ┌────┐ └──→ │ Strategy │   └─────┘   △   ┌────┴────┐    │ ConcreteStrategy │ └─────────┘ 着色部份就是常見的策略模式結構. -- ▂▂ ▄▂ T.T.L Listen 2 http://ppt.cc/jIUk ˇ ˇˇ ˇ 說什麼結束 ▃▃ http://ppt.cc/zQtB ψ髮箍 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.121.197.115

04/24 01:18, , 1F
感覺版主好聰明 好厲害...
04/24 01:18, 1F

04/24 01:23, , 2F
大推這一篇呀,受教了
04/24 01:23, 2F

04/24 01:23, , 3F
我的方法如果有另外一種strategy的繼承體系就完蛋了
04/24 01:23, 3F

04/24 01:25, , 4F
不過感覺這樣改,我要增加超多Get與Set函數 囧
04/24 01:25, 4F

04/24 01:27, , 5F
可能需要依據需求設計數種不同的Accessor
04/24 01:27, 5F

04/24 01:28, , 6F
這個感覺有點Proxy Pattern的味道在
04/24 01:28, 6F

04/24 01:39, , 7F
另外,利用private繼承+using選用需要的method很酷
04/24 01:39, 7F

04/24 01:41, , 8F
這樣就可以關閉部份的功能性
04/24 01:41, 8F

04/24 01:43, , 9F
要寫出新的Accessor完全不用更動其他class
04/24 01:43, 9F

04/24 01:43, , 10F
我覺得版主真神人也...
04/24 01:43, 10F

04/24 01:48, , 11F
我覺得沒看到這篇之前,我都不算真的會用strategy...
04/24 01:48, 11F

04/24 01:54, , 12F
我覺得看到版主這篇,都不知道該怎麼畢業了...
04/24 01:54, 12F
110424 修改類別圖, 補上關聯 ※ 編輯: loveme00835 來自: 140.121.197.115 (04/24 03:30)
文章代碼(AID): #1DikTJ0t (C_and_CPP)
文章代碼(AID): #1DikTJ0t (C_and_CPP)