1.简化习俗
1.1 信使
信使(messenger)将消息封装到一个对象中到处传递,而不是将消息的所有片段分开进行传递。没有信使,下例的translate()的代码读起来非常缺乏条理。
using namespace std;
class Point
{
public:
int x, y, z;
Point( int xi, int yi, int zi) : x( xi) , y( yi) , z( zi) { }
Point( const Point& p) : x( p. x) , y( p. y) , z( p. z) { }
friend ostream& operator << ( ostream& os, const Point& p) {
return os << "x=" << p. x << "y=" << p. y
<< "z=" << p. z;
}
} ;
class Vector
{
public:
int magnitude, direction;
Vector( int m, int d) : magnitude( m) , direction( d) { }
~ Vector( ) { }
} ;
class Space
{
public:
static Point translate( Point p, Vector v) {
p. x += v. magnitude + v. direction;
p. y += v. magnitude + v. direction;
p. z += v. magnitude + v. direction;
return p;
}
} ;
int main( int argc, char const * argv[ ] )
{
Point p1( 1 , 2 , 3 ) ;
Point p2 = Space: : translate( p1, Vector( 11 , 47 ) ) ;
cout << "p1:" << p1 << " p2:" << p2 << endl;
return 0 ;
}
1.2 收集参数
收集参数的工作是从传递给它的函数中获取信息。通常,当收集参数被传递给多个函数的时候使用它。 容器对于收集参数特别有用,因为它已经设置为动态增加对象
class CollectingParameter : public vector< string> { } ;
class Filter
{
public:
void f( CollectingParameter& cp) {
cp. push_back( "accumulating" ) ;
}
void g( CollectingParameter& cp) {
cp. push_back( "items" ) ;
}
void h( CollectingParameter& cp) {
cp. push_back( "as we go" ) ;
}
} ;
int main( int argc, char const * argv[ ] )
{
Filter filter ;
CollectingParameter cp;
filter . f( cp) ;
filter . g( cp) ;
filter . h( cp) ;
vector< string> : : iterator it = cp. begin( ) ;
while ( it != cp. end( ) )
cout << * it+ + << endl;
cout << endl;
return 0 ;
}
1.3 单件
单件允许一个类有且仅有一个实例 的方法 由于Singleton::instance()返回的是同一个对象,因此对s2进行set操作就是对s进行set操作
#include <iostream>
using namespace std;
class Singleton
{
static Singleton s;
int i;
Singleton ( int x) : i ( x) { }
Singleton& operator = ( Singleton& ) ;
Singleton ( const Singleton& ) ;
public :
static Singleton& instance ( ) { return s; }
int getValue ( ) { return i; }
void setValue ( int x) { i = x; }
} ;
Singleton Singleton:: s ( 47 ) ;
int main ( ) {
Singleton& s = Singleton:: instance ( ) ;
cout << s. getValue ( ) << endl;
Singleton& s2 = Singleton:: instance ( ) ;
s2. setValue ( 9 ) ;
cout << s. getValue ( ) << endl;
}
1.4 命令:选择操作
命令模式对于消除代码间的耦合——清理代码有着重要的影响。 最直观的角度来看,命令模式是一个函数对象。通过将函数封装为对象,就能够以参数的形式将其传递给其他函数或者对象,告诉它们在履行请求的过程中执行特定的操作。
using namespace std;
class Command
{
public:
virtual void execute( ) = 0 ;
} ;
class Hello : public Command
{
public:
void execute( ) { cout << "Hello" << endl; }
} ;
class World : public Command {
public:
void execute( ) { cout << "World!" << endl; }
}
class IAm : public Command
{
public:
void execute( ) { cout << "I am the command pattern" << endl; }
} ;
class Macro
{
vector< Command* > commands;
public:
void add( Command* c) { commands. push_back( c) ; }
void run( ) {
vector< Command* > : : iterator it = commands. begin( ) ;
while ( it != commands. end( ) )
( * it+ + ) - > execute( ) ;
}
} ;
int main( int argc, char const * argv[ ] )
{
Macro macro;
macro. add( new Hello) ;
macro. add( new World) ;
macro. add( new IAm) ;
macro. run( ) ;
return 0 ;
}
1.5 消除对象耦合
代理(Proxy)模式和状态(State)模式都提供一个代理(Surrogate)类。代码与代理类打交道,而做实际工作的类隐藏在代理类背后。当调用代理类中的一个函数时,代理类仅转而去调用实现类中相应的函数。 从结构上看,代理模式是状态模式的一个特例。但是二者的内涵(intent)不同,不可理解为二者是相同的设计模式。 基本思想:代理(Surrogate)类派生自一个基类,由平行地派生自同一个基类的一个或多个类提供实际的实现。当一个代理对象被创建的时候,一个实现对象就分配给了它,代理对象就将函数调用发给实现对象。 从结构上来看,代理模式和状态模式的区别很简单:代理模式只有一个实现类,而状态模式有多个(一个以上)实现。(在GoF中)认为这两种设计模式的应用也不同:代理模式控制对其实现类的访问,而状态模式动态地改变其实现类。
1.5.1 代理模式:作为其他对象的前端
#include <iostream>
using namespace std;
class ProxyBase
{
public :
virtual void f ( ) = 0 ;
virtual void g ( ) = 0 ;
virtual void h ( ) = 0 ;
~ ProxyBase ( ) { }
} ;
class Implementation : public ProxyBase
{
public :
virtual void f ( ) { cout << "Implementation.f()" << endl; }
virtual void g ( ) { cout << "Implementation.g()" << endl; }
virtual void h ( ) { cout << "Implementation.h()" << endl; }
} ;
class Proxy : public ProxyBase
{
ProxyBase* implementation;
public :
Proxy ( ) { implementation = new Implementation ( ) ; }
~ Proxy ( ) { delete implementation; }
void f1 ( ) {
implementation- > f ( ) ;
}
void g1 ( ) {
implementation- > g ( ) ;
}
void h1 ( ) {
implementation- > h ( ) ;
}
} ;
int main ( ) {
Proxy p;
p. f ( ) ;
p. g ( ) ;
p. h ( ) ;
}
1.5.2 状态模式:改变对象的行为
#include <iostream>
using namespace std;
class ProxyBase
{
public :
virtual void f ( ) = 0 ;
virtual void g ( ) = 0 ;
virtual void h ( ) = 0 ;
~ ProxyBase ( ) { }
} ;
class Implementation : public ProxyBase
{
public :
virtual void f ( ) { cout << "Implementation.f()" << endl; }
virtual void g ( ) { cout << "Implementation.g()" << endl; }
virtual void h ( ) { cout << "Implementation.h()" << endl; }
} ;
class Proxy : public ProxyBase
{
ProxyBase* implementation;
public :
Proxy ( ) { implementation = new Implementation ( ) ; }
~ Proxy ( ) { delete implementation; }
void f1 ( ) {
implementation- > f ( ) ;
}
void g1 ( ) {
implementation- > g ( ) ;
}
void h1 ( ) {
implementation- > h ( ) ;
}
} ;
int main ( ) {
Proxy p;
p. f ( ) ;
p. g ( ) ;
p. h ( ) ;
}
1.6 模板方法模式
模板方法模式的一个重要特征是它的定义在基类中并且不能改动——模板方法模式就是”坚持相同的代码“。它调用其他基类函数(这些基类函数被子类重写)以便完成其工作,但是客户程序员不必直接调用这些函数:
#include <iostream>
using namespace std;
class ApplicationFramework
{
protected :
virtual void customize1 ( ) = 0 ;
virtual void customize2 ( ) = 0 ;
public :
void templateMethod ( ) {
for ( int i = 0 ; i < 5 ; ++ i)
{
customize1 ( ) ;
customize2 ( ) ;
}
}
} ;
class MyApp : public ApplicationFramework
{
protected :
void customize1 ( ) { cout << "Hello " ; }
void customize2 ( ) { cout << "World! " << endl; }
} ;
int main ( ) {
MyApp app;
app. templateMethod ( ) ;
}
驱动应用程序运行的”引擎“就是模板方法模式。在GUI应用程序中,这个”引擎“就是主要的事件环。
1.7 策略模式:运行时选择算法
”策略“的意思是:可以使用多种方法来解决某个问题。
#include <iostream>
using namespace std;
class NameStrategy
{
public :
virtual void greet ( ) = 0 ;
} ;
class SayHi : public NameStrategy
{
public :
void greet ( ) {
cout << "Hi!How's it going?" << endl;
}
} ;
class Ignore : public NameStrategy
{
public :
void greet ( ) {
cout << "(Pretend I don't see you)" << endl;
}
} ;
class Admission : public NameStrategy
{
public :
void greet ( ) {
cout << "I am sorry. I forger your name." << endl;
}
} ;
class Context
{
NameStrategy& strategy;
public :
Context ( NameStrategy& strat) : strategy ( strat) { }
void greet ( ) { strategy. greet ( ) ; }
} ;
int main ( ) {
SayHi sayhi;
Ignore ignore;
Admission admission;
Context c1 ( sayhi) , c2 ( ignore) , c3 ( admission) ;
c1. greet ( ) ;
c2. greet ( ) ;
c3. greet ( ) ;
}
1.8 工厂模式:封装对象的创建
当发现需要添加新的类型到一个系统中时,最明智的首要步骤就是用多态机制为这些新类创建一个共同的接口。 用一个通用的工厂(factory)来创建对象,而不允许将创建对象的代码散布于整个系统。如果程序中所有需要创建对象的代码都转到这个工厂执行,那么在增加新对象时所要做的全部工作就是只需修改工厂。
Shape* Shape: : factory( const string& type ) throw( Shape: : BadShapeCreation) {
if ( type == "Circle" ) return new Circle;
if ( type == "Square" ) return new Square;
throw BadShapeCreation( type ) ;
}
string sl[ ] = { "Circle" , "Square" , "Square" , "Circle" , "Circle" , "Circle" , "Square" } ;
在添加新的Shape类型时,函数factory()是当前系统中惟一需要修改的代码。
shapes. push_back( Shape: : factory( sl[ i] ) ) ;
using namespace std;
class Shape
{
public:
virtual void draw( ) = 0 ;
virtual void erase( ) = 0 ;
virtual ~ Shape( ) { }
class BadShapeCreation : public logic_error {
public:
BadShapeCreation( string type ) : logic_error( "Cannot create type " + type ) { }
} ;
static Shape* factory( const string& type ) throw( BadShapeCreation) ;
} ;
class Circle : public Shape
{
Circle( ) { }
friend class Shape ;
public:
void draw( ) { cout << "Circle::draw" << endl; }
void erase( ) { cout << "Circle::erase" << endl; }
~ Circle( ) { cout << "Circle::~Circle" << endl; }
} ;
class Square : public Shape
{
Square( ) { }
friend class Shape ;
public:
void draw( ) { cout << "Square::draw" << endl; }
void erase( ) { cout << "Square::erase" << endl; }
~ Square( ) { cout << "Square::~Square" << endl; }
} ;
Shape* Shape: : factory( const string& type ) throw( Shape: : BadShapeCreation) {
if ( type == "Circle" ) return new Circle;
if ( type == "Square" ) return new Square;
throw BadShapeCreation( type ) ;
}
string sl[ ] = { "Circle" , "Square" , "Square" , "Circle" , "Circle" , "Circle" , "Square" } ;
int main( int argc, char const * argv[ ] )
{
vector< Shape* > shapes;
try {
for ( int i = 0 ; i < sizeof sl / sizeof sl[ 0 ] ; + + i)
shapes. push_back( Shape: : factory( sl[ i] ) ) ;
} catch ( Shape: : BadShapeCreation e) {
cout << e. what( ) << endl;
return EXIT_FAILURE;
}
for ( int i = 0 ; i < shapes. size( ) ; i+ + ) {
shapes[ i] - > draw( ) ;
shapes[ i] - > erase( ) ;
}
return 0 ;
}
1.9 抽象工厂
#include <iostream>
#include <string>
using namespace std;
class Obstacle
{
public :
virtual void action = 0 ;
} ;
class Player
{
public :
virtual void Interactwith ( Obstacle* ) = 0 ;
} ;
class Kitty : public Player
{
public :
virtual virtual Interactwith ( Obstacle* ob) {
cout << "Kitty has encounted a " << endl;
ob- > action;
}
} ;
class KungfuGuy : public Player
{
public :
virtual void Interactwith ( Obstacle* ob) {
cout << "KungfuGuy now battles against a " << endl;
ob- > action;
}
} ;
class Puzzle : public Obstacle
{
public :
void action ( ) {
cout << "Puzzle!!!" << endl;
}
} ;
class NastyWeapon : public Obstacle
{
public :
void action ( ) {
cout << "NastyWeapon!!!" << endl;
}
} ;
class GameElementFactory
{
public :
virtual Player* makePlayer ( ) = 0 ;
virtual Obstacle* makeObstacle ( ) = 0 ;
} ;
class KittiesAndPuzzles : public GameElementFactory
{
public :
virtual Player* makePlayer ( ) {
return new NastyWeapon;
}
} ;
class KillAndDismember : public GameElementFactory
{
public :
virtual Player* makePlayer ( ) { return new KungfuGuy; }
virtual Obstacle* makeObstacle ( ) {
return new NastyWeapon;
}
} ;
class GameEnvironment
{
GameElementFactory* gef;
Player* p;
Obstacle* ob;
public :
GameEnvironment ( GameElementFactory* factory) : gef ( factory) , p ( factory- > makePlayer ( ) ) , ob ( factory- > makeObstacle ( ) ) { }
void play ( ) { p- > Interactwith ( ob) ; }
~ GameEnvironment{
delete p;
delete ob;
delete gef;
}
} ;
int main ( int argc, char const * argv[ ] )
{
GameEnvironment g1 ( new KittiesAndPuzzles) , g2 ( new KillAndDismember)
g1. play ( ) ;
g2. play ( ) ;
return 0 ;
}