软体样式(Design Pattern )
之应用
※ 高焕堂
自从1991年以来﹐样式观念和理论逐渐成为物件导向(OO)领域中最热门的话题之一。本文探讨如何使用样式﹐解决软体上的常见问题。
什么是样式?
顾名思意﹐样式是人们遭遇到特定问题时﹐大家惯用的应付方式。样式可用来解决问题﹐而且是有效、可靠的。掌握愈多样式﹐运用愈成熟﹐就愈是杰出的设计专家。
依据样式理论大师亚历山大(Christopher Alexander) 之定义﹕
「样式是某外在环境(Context) 下﹐对特定问题(Problem)的惯用解决之道(Solution)」
例如﹐在平坦的校园里(Context) ﹐下述两项需求是互相冲突的﹕
◎学生需要交通工具代步。
◎校园空气必须保持清洁。
就产生问题(Problem) 了﹐该如何化解呢﹖在一般校园里﹐惯用解决之道(Solution)是﹕规定在校园中只能骑自行车﹐不能骑有污染的机车和汽车。此解决之道是否有效﹐是取决于外在环境(Context) 。例如﹐在不平坦的清华大学校园中﹐上述解决之道就无效用了。于是另找解决方案来处理这问题了﹔例如﹐提供电动机车供学生在校园中使用。
自从1991年以来﹐亚历山大的样式理论逐渐应用于OO软体的设计上﹐可解决软体设计上的问题。例如﹐软体设计时﹐常见下述问题﹕
软体模组(Module)之间的相依性太高﹐不易个别抽换模组﹐软体的「软」性就降低了。
可利用样式解决这种问题﹐求增强模组之间的独立性﹐提高软体的弹性(Flexibility) ﹐降低软体的维护费用﹗
设计样式(Design Pattern)
在Erich Gamma 等人合着的﹕
"Design Patterns: Elements of Reusable Object-Oriented Software"
一书列出23种软体样式﹐可解决软体设计上的特定问题。本文举例说明其中的3 种样式﹐看看它们的应用情形。
1. Factory Method 样式
2. Abstract Factory 样式
3. Builder样式
首先拿个简单程式来叙述「问题」之所在﹕
//// p1.cpp
class Integer {
int value;
public:
Integer() { value=100; }
void DisplayValue()
{ cout << value << endl; }
};
class Document {
Integer *pi;
public:
Document() { pi = new Integer(); }
void DisplayData()
{ pi->DisplayValue(); }
};
void main() {
Document d;
d.DisplayData();
}
//// end
两类别的相依性很高﹐原因是﹕Document类别直接使用Integer 字眼﹐且使用两次。于是﹐问题是﹕
「若必须将Integer 类别名称改为Float 时﹐得更换 Document类别中的Integer 字眼」。
亦即﹐抽换Integer 类别时﹐会牵连到Document类别﹐抽换过程将不会很顺畅﹗藉由抽象类别﹐可解决部分问题,如下﹕
//// p2.cpp
class Data {
public:
virtual void DisplayValue()=0;
};
class Integer : public Data {
int value;
public:
Integer() { value=100; }
virtual void DisplayValue()
{ cout << value << endl; }
};
class Document {
Data *pd;
public:
Document() { pd=new Integer(); }
void DisplayData()
{ pd->DisplayValue(); }
};
void main() {
Document d;
d.DisplayData();
}
//// end
&nb