在strategy pattern中,為了讓各strategy能方便存取原來物件的所有public member function,我們常用*this將整個物件傳給各strategy,這樣的設計並沒有什麼不好,但各strategy和原物件過於tight coupling,導致各strategy難以再和其他各物件搭配,本文使用template解決此問題。
在(原創) 我的Design Pattern之旅:Strategy Pattern (初級) (Design Pattern) (C++) (OO C++) (Template C++)中,我們使用了strategy pattern讓Grapher能畫Triangle、Circle和Square
因為需求再次改變,:D,我們希望Grapher能將文字印在各Shape中,執行結果如下
為了達到此需求,我們可以將IShape interface改成
但若將來需求再改變,希望畫的不是文字,而是一張圖片,那interface又必須再變動,為了一勞永逸,我們會將整個物件傳給各strategy,IShape interface改成如下
Grapher::drawShpae()將*this傳給各strategy
完整的程式碼如下
執行結果
這樣的設計看似完美,但IShape和Grapher相依程度太高,若將來有個Painter class,和Grapher完全不同,沒有任何繼承或多型的關係,但想重複使用IShape interface的strategy,這樣的設計就無法讓Painter使用了。若我們能讓IShape interface的draw()不再只限定Grapher型別,改用template,就能讓將來所有型別都能使用IShape interface。
我們用泛型T取代了Grapher,任何型別都可傳進IShape::draw()。
完整程式碼如下
執行結果
Conclusion
泛型的應用相當廣,在此範例僅僅是泛型的小小應用,在OOP世界使用strategy pattern,常將*this傳給strategy,若搭配GP可讓strategy pattern的resuse程度更高。
See Also
(原創) 我的Design Pattern之旅[1]:Strategy Pattern (初級) (Design Pattern) (C++) (OO C++) (Template C++)
(原創) 我的Design Pattern之旅[4]:使用Generic改進Strategy Pattern (高級) (Design Pattern) (C#) (Generic)