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

编程入门 行业动态 更新时间:2024-10-28 02:33:56

Think in in C++[vol2]【10】设计<a href=https://www.elefans.com/category/jswz/34/1771241.html style=模式"/>

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 implementationvoid 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 implementationvoid 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;
}

更多推荐

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

本文发布于:2023-07-28 19:46:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1291667.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!