附录A: 余下的模式
1桥接 Bridge 不只改变实现, 也改变抽象
>优点 将实现解耦 让其和UI之间不再绑定; 抽象和实现可以独立扩展互不影响; 对于"具体的抽象类"所做的改变不影响客户
>用途和缺点 适合需要跨越多个平台的图形和窗口系统上; 当需要用不同的方式改变接口和实现时; 增加了复杂度;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//***********Bridge***********
class
ITVImp
{
public
:
virtual
void
onImp() = 0;
};
class
IRemoteControl
{
public
:
virtual
void
on() = 0;
virtual
void
SetImp(ITVImp* pImp) { mpImp = pImp; }
virtual
ITVImp* GetImp() {
return
mpImp;}
private
:
ITVImp* mpImp;
};
class
RCAImp :
public
ITVImp
{
public
:
virtual
void
onImp();
};
class
ConcreteRemoteControl :
public
IRemoteControl
{
public
:
ConcreteRemoteControl();
virtual
void
on();
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
void
RCAImp::onImp()
{
cout <<
"RCAImp"
<< endl;
}
ConcreteRemoteControl::ConcreteRemoteControl()
{
SetImp(
new
RCAImp());
}
void
ConcreteRemoteControl::on()
{
((RCAImp*)GetImp())->onImp();
}
//Bridge
ConcreteRemoteControl* control =
new
ConcreteRemoteControl();
control->on();
|
PIMPL模式 Private Class Data Pattern 隐藏类的内部实现和数据 用户只能看到public API
2生成器 Builder 封装一个产品的构造过程 允许按步骤构造
>优点 将复杂对象的创建过程封装起来; 允许对象通过多个步骤创建 可以改变过程(工厂模式只有一个步骤); 向客户隐藏产品内部的表现; 产品的表现可替换 客户只看到抽象的接口
>用途和缺点 创建组合结构; 与工厂模式相比 采用生成器创建对象的客户需要具备更多领域知识;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//***********Builder***********
class
Result
{
public
:
void
show();
string sPartA;
string sPartB;
};
class
IBuilder
{
public
:
virtual
void
buildA(string a) = 0;
virtual
void
buildB(string b) = 0;
//...
virtual
Result* getResult() = 0;
};
class
ResBuilder :
public
IBuilder
{
public
:
ResBuilder();
virtual
void
buildA(string a);
virtual
void
buildB(string b);
virtual
Result* getResult() {
return
mpRes;};
private
:
Result* mpRes;
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
ResBuilder::ResBuilder()
{
mpRes =
new
Result();
}
void
ResBuilder::buildA(string a)
{
mpRes->sPartA = a;
}
void
ResBuilder::buildB(string b)
{
mpRes->sPartB = b;
}
void
Result::show()
{
cout << sPartA + sPartB << endl;
}
//Builder
ResBuilder* builder =
new
ResBuilder();
builder->buildA(
"Build part A"
);
builder->buildB(
"Build part B"
);
Result* res = builder->getResult();
res->show();
|
3责任链 Chain of Responsibility 让一个以上的对象处理某个请求的时候
>优点 将请求的发送者和接收者解耦; 简化对象 使其不需要知道链的结构; 通过改变链内的成员或调动次序 允许动态新增或者删除责任
>用途和缺点 经常使用在窗口系统中 处理鼠标和键盘事件; 不保证请求一定会被执行; 不容易观察运行时的特征, 不易查错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
//***********ChainOR***********
class
IHandler;
typedef
vector <IHandler*> HANDLERVEC;
class
IHandler
{
public
:
IHandler(
int
iType) : miType(iType) {};
virtual
void
handleRequest() = 0;
virtual
int
getType() {
return
miType;}
private
:
int
miType;
};
class
ConcreteHandler :
public
IHandler
{
public
:
ConcreteHandler(
int
iType);
virtual
void
handleRequest();
private
:
HANDLERVEC mHandlerVec;
};
class
HandlerLev1 :
public
IHandler
{
public
:
HandlerLev1(
int
iType) : IHandler(iType) {};
virtual
void
handleRequest() {cout <<
"Handle Level1"
<< endl;};
};
class
HandlerLev2 :
public
IHandler
{
public
:
HandlerLev2(
int
iType) : IHandler(iType) {};
virtual
void
handleRequest() {cout <<
"Handle Level2"
<< endl;};
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
ConcreteHandler::ConcreteHandler(
int
iType) : IHandler(iType)
{
HandlerLev1* lev1 =
new
HandlerLev1(1);
HandlerLev2* lev2 =
new
HandlerLev2(2);
mHandlerVec.push_back(lev1);
mHandlerVec.push_back(lev2);
}
void
ConcreteHandler::handleRequest()
{
HANDLERVEC::iterator iter = mHandlerVec.begin();
for
(; iter != mHandlerVec.end(); iter++)
{
IHandler* handler = *iter;
if
(handler != NULL && getType() == handler->getType())
{
handler->handleRequest();
return
;
}
}
}
//ChainOR
ConcreteHandler* handler =
new
ConcreteHandler(1);
handler->handleRequest();
|
4蝇量 Flyweight 让某个类的一个实例能用来提供很多"虚拟实例"
>优点 减少运行时对象实例的个数 节省内存; 将许多"虚拟对象"的状态集中管理
>用途和缺点 当类有许多的实例 这些实例能被同一个方法控制的时候; 单个的逻辑实例将无法拥有独立而不同的行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//***********Flyweight***********
class
Tree
{
public
:
Tree(
int
i);
virtual
void
display(
int
x,
int
y);
virtual
int
getAge() {
return
miAge;}
private
:
int
miAge;
};
struct
TreeData
{
int
xCoord;
int
yCoord;
int
age;
};
typedef
map <
int
, Tree*> TREEMAP;
class
TreeManager
{
public
:
void
displayTrees(
int
num, TreeData data[]);
Tree* getTree(
int
age);
private
:
TREEMAP treeMap;
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
Tree::Tree(
int
i) : miAge(i) {}
void
Tree::display(
int
x,
int
y)
{
cout<<
"Coord"
<< x <<
","
<< y <<
"Age"
<<miAge<<endl;
}
void
TreeManager::displayTrees(
int
num, TreeData data[])
{
for
(
int
i = 0; i < num; i++)
{
TreeData treeData = data[i];
getTree(treeData.age)->display(treeData.xCoord, treeData.yCoord);
}
}
Tree* TreeManager::getTree(
int
age)
{
Tree* tree;
TREEMAP::iterator iter = treeMap.find(age);
if
(iter == treeMap.end())
// Save the memeory
{
tree =
new
Tree(age);
cout<<
"new a tree"
<<endl;
treeMap[age] = tree;
}
else
tree = treeMap[age];
return
tree;
}
//Flyweight
TreeData treeData[3] =
{
{10, 20, 3},
{20, 10, 5},
{30, 30, 3}
};
TreeManager treeManager;
treeManager.displayTrees(3, treeData);
|
5解释器 Interpreter 为语言创建解释器
>优点 将每一个语法规则表示成一个类; 语法由许多类表示 容易改变或扩展语言; 通过在类结构中加入新的方法 可以在解释的同时增加新的行为 例如格式美化或程序验证
>用途和缺点 需要实现一个简单的语言时; 有一个简单的语法 简单比效率更重要时; 处理脚本语言和编程语言; 当语法规则数目过大时 模式将变得非常繁复 这种情况下适合解析器/编译器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//***********Interpreter***********
class
Context
{
public
:
Context(string s,
int
d) : statement(s), data(d) {};
string getState() {
return
statement;}
int
getData() {
return
data;}
private
:
string statement;
int
data;
};
class
IExpression
{
public
:
virtual
void
Interpreter(Context context) = 0;
};
class
Expression :
public
IExpression
{
public
:
void
Interpreter(Context context);
void
parseState(string);
void
parseData(
int
);
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
void
Expression::Interpreter(Context context)
{
parseState(context.getState());
parseData(context.getData());
}
void
Expression::parseState(string s)
{
cout <<
"string: "
<< s << endl;
}
void
Expression::parseData(
int
d)
{
cout <<
"data: "
<< d << endl;
}
//Interpreter
Context context(
"test"
, 1);
Expression expression;
expression.Interpreter(context);
|