Think in in C++[vol2]【10】设计模式

1.简化习俗

1.1 信使
  • 信使(messenger)将消息封装到一个对象中到处传递,而不是将消息的所有片段分开进行传递。没有信使,下例的translate()的代码读起来非常缺乏条理。
#include <iostream>
#include <string>
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 收集参数
  • 收集参数的工作是从传递给它的函数中获取信息。通常,当收集参数被传递给多个函数的时候使用它。
  • 容器对于收集参数特别有用,因为它已经设置为动态增加对象
#include <iostream>
#include <string>
#include <vector>

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&);  //放在private,根本不会被调用
    Singleton(const Singleton&);  //放在private,根本不会被调用
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);
    //由于Singleton::instance()返回的是同一个对象,因此对s2进行set操作就是对s进行set操作
    cout << s.getValue() << endl;
}
1.4 命令:选择操作
  • 命令模式对于消除代码间的耦合——清理代码有着重要的影响。
  • 最直观的角度来看,命令模式是一个函数对象。通过将函数封装为对象,就能够以参数的形式将其传递给其他函数或者对象,告诉它们在履行请求的过程中执行特定的操作。
#include <iostream>
#include <vector>
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; }
    //Forward calls to the 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; }
    //Forward calls to the 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();
    }
  }
};

//Create a new "application":
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;
	}
};

//The Context controls the strategy:
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]));
#include <iostream>
#include <stdexcept>
#include <cstddef>
#include <vector>
using namespace std;

# 为了确保对象的创建只能发生在函数factory()中,Shape的特定类型的构造函数被设为私有,同时Shape被声明为友元类,因此factory()能够访问这些构造函数。
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;
    }
};

//The abstract factory
class GameElementFactory
{
public:
    virtual Player* makePlayer() = 0;
    virtual Obstacle* makeObstacle() = 0;
};

//Concrete factories
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值