传统网站建设 成本,旅游网站制作方法,桂林两江四湖附近酒店,手机网站建设软件下载代理模式#xff1a;Proxy
动机 “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方案。在面向对象系统中#xff0c;直接食用某些对象会带来很多问题#xff0c;作为间接层的proxy对象便是解决这一问题的常见手段。 2.伪代码#xff1a;
class ISubject{
pu…代理模式Proxy
动机 “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方案。在面向对象系统中直接食用某些对象会带来很多问题作为间接层的proxy对象便是解决这一问题的常见手段。 2.伪代码
class ISubject{
public:virtual void process();
};//Proxy的设计
class SubjectProxy: public ISubject{public:virtual void process(){//对RealSubject的一种间接访问//....}
};class ClientApp{ISubject* subject;public:ClientApp(){subjectnew SubjectProxy();}void DoTask(){//...subject-process();//....}
};3.理解 copy on write就是这个思想。看类图以及代码简单但是它真正的实现可能会很复杂。 4.类图 适配器Adapter
动机 需要将一些现存的对象放在新的环境中应用但是新环境要求的接口是这些现存对象所不能满足的。如何应对这种迁移的变化如何既能利用现存对象的良好实现同时又能满足新的应用环境的要求接口 2.伪代码
//目标接口新接口
class ITarget{
public:virtual void process()0;
};//遗留接口老接口
class IAdaptee{
public:virtual void foo(int data)0;virtual int bar()0;
};//遗留类型
class OldClass: public IAdaptee{//....
};//对象适配器
class Adapter: public ITarget{ //继承
protected:IAdaptee* pAdaptee;//组合public:Adapter(IAdaptee* pAdaptee){this-pAdapteepAdaptee;}virtual void process(){int datapAdaptee-bar();pAdaptee-foo(data);}
};//类适配器
class Adapter: public ITarget,protected OldClass{ //多继承
}int main(){IAdaptee* pAdapteenew OldClass();ITarget* pTargetnew Adapter(pAdaptee);pTarget-process();}class stack{deqeue container;};class queue{deqeue container;};3.类图 中介者模式Mediator
动机 会出现多个对象互相交互的情况对象之间通常会维持一种复杂的引用关系如果遇到一些需求的更改这种直接的引用关系将会面临不断变化。 2.伪代码
与facade相同思想无代码3.理解 Colleague和Mediator两个类之间相互依赖Colleague之间不相互依赖但是会通过Mediator间接依赖。把直接依赖关系变为间接依赖关系。facade用于解耦内部与外部之间的关系中介者相当于解耦facade内部之间的关系。 4.类图 状态变化
在组件变化构建过程中某些对象的状态经常面临变化如何对这些变化进行有效的管理同时又维持高层模块的稳定
状态模式State
动机 某些对象的状态如果改变其行为也会随之改变。如何在运行时根据对象的状态来透明的更改对象的行为而不会为对象操作和状态转变之间引入紧耦合 2.伪代码
class NetworkState{public:NetworkState* pNext;virtual void Operation1()0;virtual void Operation2()0;virtual void Operation3()0;virtual ~NetworkState(){}
};class OpenState :public NetworkState{static NetworkState* m_instance;
public:static NetworkState* getInstance(){if (m_instance nullptr) {m_instance new OpenState();}return m_instance;}void Operation1(){//**********pNext CloseState::getInstance();}void Operation2(){//..........pNext ConnectState::getInstance();}void Operation3(){//$$$$$$$$$$pNext OpenState::getInstance();}};class CloseState:public NetworkState{ }
//...class NetworkProcessor{NetworkState* pState;public:NetworkProcessor(NetworkState* pState){this-pState pState;}void Operation1(){//...pState-Operation1();pState pState-pNext;//...}void Operation2(){//...pState-Operation2();pState pState-pNext;//...}void Operation3(){//...pState-Operation3();pState pState-pNext;//...}};备忘录模式Memento
动机 某些对象的状态在转化过程中可能有某种需要要求程序能够回溯到对象之前处于某个点时的状态。如何在不破坏封装性的前提下实现这个任务呢 2.伪代码 class Memento
{string state;//..
public:Memento(const string s) : state(s) {}string getState() const { return state; }void setState(const string s) { state s; }
};class Originator
{string state;//....
public:Originator() {}Memento createMomento() {Memento m(state);return m;}void setMomento(const Memento m) {state m.getState();}
};int main()
{Originator orginator;//捕获对象状态存储到备忘录Memento mem orginator.createMomento();//... 改变orginator状态//从备忘录中恢复orginator.setMomento(mem);
}3.理解 备忘录就是存储一个类的状态快照在需要的时候设置为备忘录中的状态。核心是隐藏信息。这个模式有些过时。其实就是对象序列化。 4.类图 数据结构
一些组件在内部具有特定的数据结构如果让客户程序依赖于这些特定的数据结构将破坏组件的复用性。这个时候将这些数据结构封装在内部对外提供统一的接口来实现与特定的数据结构无关的访问。
组合模式Composite
动机 如何将客户代码与复杂的对象容器结构解耦让对象容器自己实现自身的复杂结构从而使得客户代码就像处理简单对象一样来处理复杂的对象容器 2.伪代码
#include iostream
#include list
#include string
#include algorithmusing namespace std;class Component
{
public:virtual void process() 0;virtual ~Component(){}
};//树节点
class Composite : public Component{string name;listComponent* elements;
public:Composite(const string s) : name(s) {}void add(Component* element) {elements.push_back(element);}void remove(Component* element){elements.remove(element);}void process(){//1. process current node//2. process leaf nodesfor (auto e : elements)e-process(); //多态调用}
};//叶子节点
class Leaf : public Component{string name;
public:Leaf(string s) : name(s) {}void process(){//process current node}
};void Invoke(Component c){//...c.process();//...
}int main()
{Composite root(root);Composite treeNode1(treeNode1);Composite treeNode2(treeNode2);Composite treeNode3(treeNode3);Composite treeNode4(treeNode4);Leaf leaf1(left1);Leaf leaf2(left2);root.add(treeNode1);treeNode1.add(treeNode2);treeNode2.add(leaf1);root.add(treeNode3);treeNode3.add(treeNode4);treeNode4.add(leaf2);process(root);process(leaf2);process(treeNode3);}3.理解 对象组合成树形结构。和装饰器有点像不仅has-a而且is-a。将一对多的关系替换成一对一的关系。 4.类图 迭代器Iterator
动机 提供一种方法顺序访问一个聚合对象中的各个元素而又不暴露该对象的内部表示。 2.伪代码
templatetypename T
class Iterator
{
public:virtual void first() 0;virtual void next() 0;virtual bool isDone() const 0;virtual T current() 0;
};templatetypename T
class MyCollection{public:IteratorT GetIterator(){//...}};templatetypename T
class CollectionIterator : public IteratorT{MyCollectionT mc;
public:CollectionIterator(const MyCollectionT c): mc(c){ }void first() override {}void next() override {}bool isDone() const override{}T current() override{}
};void MyAlgorithm()
{MyCollectionint mc;Iteratorint iter mc.GetIterator();for (iter.first(); !iter.isDone(); iter.next()){cout iter.current() endl;}}3.理解 对C来说面向对象的迭代器已经过时了。STL中的迭代器是泛型编程思想。运行时绑定是没有编译时绑定效率高的。 4.类图 职责链模式Chain Of Responsibility
动机 一个请求可能有多个接收者但是真正的接受者也就是去处理这个请求的只有一个。这时请求发送者与接受者的耦合可能出现变化脆弱的情况。 2.伪代码
#include iostream
#include stringusing namespace std;enum class RequestType
{REQ_HANDLER1,REQ_HANDLER2,REQ_HANDLER3
};class Reqest
{string description;RequestType reqType;
public:Reqest(const string desc, RequestType type) : description(desc), reqType(type) {}RequestType getReqType() const { return reqType; }const string getDescription() const { return description; }
};class ChainHandler{ChainHandler *nextChain;void sendReqestToNextHandler(const Reqest req){if (nextChain ! nullptr)nextChain-handle(req);}
protected:virtual bool canHandleRequest(const Reqest req) 0;virtual void processRequest(const Reqest req) 0;
public:ChainHandler() { nextChain nullptr; }void setNextChain(ChainHandler *next) { nextChain next; }void handle(const Reqest req){if (canHandleRequest(req))processRequest(req);elsesendReqestToNextHandler(req);}
};class Handler1 : public ChainHandler{
protected:bool canHandleRequest(const Reqest req) override{return req.getReqType() RequestType::REQ_HANDLER1;}void processRequest(const Reqest req) override{cout Handler1 is handle reqest: req.getDescription() endl;}
};class Handler2 : public ChainHandler{
protected:bool canHandleRequest(const Reqest req) override{return req.getReqType() RequestType::REQ_HANDLER2;}void processRequest(const Reqest req) override{cout Handler2 is handle reqest: req.getDescription() endl;}
};class Handler3 : public ChainHandler{
protected:bool canHandleRequest(const Reqest req) override{return req.getReqType() RequestType::REQ_HANDLER3;}void processRequest(const Reqest req) override{cout Handler3 is handle reqest: req.getDescription() endl;}
};int main(){Handler1 h1;Handler2 h2;Handler3 h3;h1.setNextChain(h2);h2.setNextChain(h3);Reqest req(process task ... , RequestType::REQ_HANDLER3);h1.handle(req);return 0;
}3.理解 应用的不多。使得多个接收者都有机会处理请求从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链并沿着这条链传递请求直到有一个对象处理请求为止。 4.类图 行为变化
在组件的构建过程中组件行为的变化经常导致组件本身的剧烈变化。下面的模式将组件本身和组件的行为进行解耦
命令模式Command
动机 如何将行为请求者和行为实现者解耦 2.伪代码
#include iostream
#include vector
#include string
using namespace std;class Command
{
public:virtual void execute() 0;
};class ConcreteCommand1 : public Command
{string arg;
public:ConcreteCommand1(const string a) : arg(a) {}void execute() override{cout #1 process...argendl;}
};class ConcreteCommand2 : public Command
{string arg;
public:ConcreteCommand2(const string a) : arg(a) {}void execute() override{cout #2 process...argendl;}
};class MacroCommand : public Command
{vectorCommand* commands;
public:void addCommand(Command *c) { commands.push_back(c); }void execute() override{for (auto c : commands){c-execute();}}
};int main()
{ConcreteCommand1 command1(receiver, Arg ###);ConcreteCommand2 command2(receiver, Arg $$$);MacroCommand macro;macro.addCommand(command1);macro.addCommand(command2);macro.execute();}3.理解 有点和仿函数思想类似。将一个请求封装成一个对象从而使你可用不同的请求对客户进行参数化。 4.类图 访问器模式Visitor
动机 在软件构件的过程中由于需求的改变某些类层次结构中常常需要增加新的行为如果直接在基类中作出修改将会给子类带来繁重的变更负担甚至破坏原有设计。 2.伪代码
#include iostream
using namespace std;class Visitor;class Element
{
public:virtual void accept(Visitor visitor) 0; //第一次多态辨析virtual ~Element(){}
};class ElementA : public Element
{
public:void accept(Visitor visitor) override {visitor.visitElementA(*this);}};class ElementB : public Element
{
public:void accept(Visitor visitor) override {visitor.visitElementB(*this); //第二次多态辨析}};class Visitor{
public:virtual void visitElementA(ElementA element) 0;virtual void visitElementB(ElementB element) 0;virtual ~Visitor(){}
};////扩展1
class Visitor1 : public Visitor{
public:void visitElementA(ElementA element) override{cout Visitor1 is processing ElementA endl;}void visitElementB(ElementB element) override{cout Visitor1 is processing ElementB endl;}
};//扩展2
class Visitor2 : public Visitor{
public:void visitElementA(ElementA element) override{cout Visitor2 is processing ElementA endl;}void visitElementB(ElementB element) override{cout Visitor2 is processing ElementB endl;}
};int main()
{Visitor2 visitor;ElementB elementB;elementB.accept(visitor);// double dispatchElementA elementA;elementA.accept(visitor);return 0;
}3.理解 Visitor中要求具体的Element稳定这个条件通常很难保证这是这个模式的重大缺点。accept方法表示接受一个visitor这个visitor能够为该类增添新的方法。一般不用因为前提条件很苛刻。 Visitor通过双重分发来实现不更改Element层次结构的前提下在运行时透明的为类层次结构上的各个类添加新的操作。 适用于Element类层次结构稳定而其中的操作确实频繁改动的。设计思想有动的有不动的 4.类图 领域规则
某些领域变化虽然频繁但是可以抽象为某种规则。要给出该领域下的对于变化的一般性解决方案。
解析器模式Interpreter
动机 如果特定领域的某一问题比较复杂类似的结构不断出现如果使用普通的编程方式来实现将会面临非常频繁的变化。在这种情况下将特定领域的问题表达为某种语法规则下的句子然后构建一个解释器来解释这样的句子从而达到解决问题的目的。 2.伪代码 #include iostream
#include map
#include stackusing namespace std;class Expression {
public:virtual int interpreter(mapchar, int var)0;virtual ~Expression(){}
};//变量表达式
class VarExpression: public Expression {char key;public:VarExpression(const char key){this-key key;}int interpreter(mapchar, int var) override {return var[key];}};//符号表达式
class SymbolExpression : public Expression {// 运算符左右两个参数
protected:Expression* left;Expression* right;public:SymbolExpression( Expression* left, Expression* right):left(left),right(right){}};//加法运算
class AddExpression : public SymbolExpression {public:AddExpression(Expression* left, Expression* right):SymbolExpression(left,right){}int interpreter(mapchar, int var) override {return left-interpreter(var) right-interpreter(var);}};//减法运算
class SubExpression : public SymbolExpression {public:SubExpression(Expression* left, Expression* right):SymbolExpression(left,right){}int interpreter(mapchar, int var) override {return left-interpreter(var) - right-interpreter(var);}};Expression* analyse(string expStr) {stackExpression* expStack;Expression* left nullptr;Expression* right nullptr;for(int i0; iexpStr.size(); i){switch(expStr[i]){case :// 加法运算left expStack.top();right new VarExpression(expStr[i]);expStack.push(new AddExpression(left, right));break;case -:// 减法运算left expStack.top();right new VarExpression(expStr[i]);expStack.push(new SubExpression(left, right));break;default:// 变量表达式expStack.push(new VarExpression(expStr[i]));}}Expression* expression expStack.top();return expression;
}void release(Expression* expression){//释放表达式树的节点内存...
}int main(int argc, const char * argv[]) {string expStr ab-cd-e;mapchar, int var;var.insert(make_pair(a,5));var.insert(make_pair(b,2));var.insert(make_pair(c,1));var.insert(make_pair(d,6));var.insert(make_pair(e,10));Expression* expression analyse(expStr);int resultexpression-interpreter(var);coutresultendl;release(expression);return 0;
}3.理解 可以理解为四则运算的运算树。使用场景为业务规则频繁变化且类似的结构重复出现并且容易简单简单小而简单的问题抽象为有规则的问题。 4.类图 总结 模版方法用于制定一套模板别人来用的时候按照模板实现策略模式方便新增策略只需新增一个子类观察者模式方便通知消息装饰模式方便拓展功能桥模式用于桥接两个向不同纬度变化的类这个桥就是一个类中组合另外一个类工厂方法创建对象解耦合抽象工厂工厂的工厂要生产一系列的产品这一系列产品需要配套原型方法有clone方法来完成对象创建构建者分步骤构建一个对象将表示和构建分离单件模式保证在内存中一个类只存在一个实例享元模式运用共享技术有效地支持大量细粒度的对象大量大量线程池门面模式不管facade内部怎么变化对于用户来说接口都是一样的代理模式就像VPN一样间接控制。适配器改变原始类接口适配新类。比如STL中的stack中介者模式把直接依赖关系变为间接依赖关系状态模式将策略模式的策略改为状态备忘录模式存储一个类的状态快照在需要的时候设置为备忘录中的状态组合模式对象组合成树形结构。将一对多的关系替换成一对一的关系迭代器STL中的迭代器思想职责链处理请求的对象连成一条链命令模式将行为抽象为对象有点和仿函数类似访问器模式使用双重分发的机制透明的添加新的操作解释器模式四则运算树 参考文章侯捷C八部曲笔记三、设计模式_侯捷c设计模式-CSDN博客