談到 Design Patterns,有興趣的人可以看看這一系列對 Erich Gamma 的訪談:
- Part I: How to Use Design Patterns
- Part II: Erich Gamma on Flexibility and Reuse
- Part III: Design Principles from Design Patterns
Erich Gamma 談到如何使用 DP 以及經過這十年他想法的一些改變。DP 固然是 programmer 設計程式時的一大利器,然而水可載舟亦可覆舟,誤用 DP 往往會造成過度的設計以及沒有必要的彈性。例如下面這個我很久以前看過的一個實際例子:
class Toy
{};
class Barbie : public Toy
{};
class Lego : public Toy
{};
class ToyFactory
{
public:
static ToyFactory* Instance();
virtual Toy* CreateToy(LPCTSTR id);
protected:
ToyFactory();
virtual ~ToyFactory();
private:
static ToyFactory* m_pToyFactory;
};
ToyFactory * ToyFactory::m_pToyFactory = NULL;
ToyFactory::ToyFactory()
{}
ToyFactory::~ToyFactory()
{}
ToyFactory * ToyFactory::Instance()
{
if (!m_pToyFactory)
m_pToyFactory = new ToyFactory;
return m_pToyFactory;
}
Toy* ToyFactory::CreateToy(LPCTSTR id)
{
if (strcmp(id, "barbie") == 0)
return new Barbie;
else if (strcmp(id, "lego") == 0)
return new Lego;
return NULL;
}
int main()
{
ToyFactory::Instance()->CreateToy("barbie");
return 0;
}
明明一個 global function 可以做到的事卻硬要用 Factory Method 及 Singleton 這兩個 pattern 來包裝,這已經是為了 DP 而 DP。
To add flexibility, you really have to be able to justify it by a requirement. If you don’t have a requirement up front, then I wouldn’t put a hook for flexibility in my system up front.
在使用任何 Design Patterns 之前,你該想想 Erich Gamma 的這番建議。