這樣的設計看似完美,但淺在一個問題
interface IShape {
void draw(Grapher grapher);
}
規定了draw()一定要傳Grapher型別進去,若將來因為需求改變,又多了一個Painter class,且和Grapher毫無相關,既非繼承亦非多型,但又想使用這些strategy,但因為IShape已規定只能傳Grapher型別,所以Painter無法繼續使用IShape interface。
在(原創) 我的Design Pattern之旅[3]:使用template改進Strategy Pattern (OO) (Design Pattern) (C/C++) (template)中,我們已成功使用C++的template解決這種型別被限制的問題,所以我們試著也使用C#的Generic來解決。
首些我們先將IShape改用Generic
interface IShape<T> {
void draw(T grapher);
}
接著其他實做IShape<T>的程式亦需改寫成
class Triangle<T> : IShape<T> where T : IGrapher {
public void draw(T grapher) {
Console.WriteLine("Draw {0:s} in Triangle", grapher.getText());
}
}
C#多了where這個keyWord,這是我卡最久的地方,也是C# generic和C++ template不同之處,C++ template並沒有限定泛型的型別,但C# generic的泛型是『有限的泛型』,或稱『以interface為基礎的泛型』、『強型別泛型』,也就是說,C#泛型不能像C++泛型那樣天馬行空的泛型,C#泛型必須『限制』在interface下,所以where稱為『constraint』
where T : IGrapher
表示泛型T需限制在IGrapher的interface下
也因此,因為各strategy會用到物件的getText(),所以我們定義IGrapher interface一定要有getText()
interface IGrapher {
string getText();
}