设计模式总结 (一)
这篇文章总结一下各个设计模式的用途与用法:
1、工厂模式属于创建型模式,大致可以分为三类,简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式,它的主要特点是需要在工厂类中通过标签做判断,返回实例
工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
抽象工厂模式,工厂方法模式的缺点,每增加一种产品,就需要增加一个对象的工厂,抽象工厂模式的定义为提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类,及抽象工厂模式的工程基类,有所有的接口,派生出来的工厂类重写。
2、策略模式是指定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
例:
//抽象接口 class ReplaceAlgorithm { public: virtual void Replace() = 0; }; //三种具体的替换算法 class LRU_ReplaceAlgorithm : public ReplaceAlgorithm { public: void Replace() { cout<<"Least Recently Used replace algorithm"<<endl; } }; class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm { public: void Replace() { cout<<"First in First out replace algorithm"<<endl; } }; class Random_ReplaceAlgorithm: public ReplaceAlgorithm { public: void Replace() { cout<<"Random replace algorithm"<<endl; } };
方式一:直接通过参数指定,传入一个特定算法的指针。
//Cache需要用到替换算法 class Cache { private: ReplaceAlgorithm *m_ra; public: Cache(ReplaceAlgorithm *ra) { m_ra = ra; } ~Cache() { delete m_ra; } void Replace() { m_ra->Replace(); } };
方式二:也是直接通过参数指定,只不过不是传入指针,而是一个标签。这样客户只要知道算法的相应标签即可,而不需要知道算法的具体定义。
//Cache需要用到替换算法 enum RA {LRU, FIFO, RANDOM}; //标签 class Cache { private: ReplaceAlgorithm *m_ra; public: Cache(enum RA ra) { if(ra == LRU) m_ra = new LRU_ReplaceAlgorithm(); else if(ra == FIFO) m_ra = new FIFO_ReplaceAlgorithm(); else if(ra == RANDOM) m_ra = new Random_ReplaceAlgorithm(); else m_ra = NULL; } ~Cache() { delete m_ra; } void Replace() { m_ra->Replace(); } };
方式三:利用模板实现。算法通过模板的实参指定。当然了,还是使用了参数,只不过不是构造函数的参数。在策略模式中,参数的传递难以避免,客户必须指定某种算法。
//Cache需要用到替换算法 template <class RA> class Cache { private: RA m_ra; public: Cache() { } ~Cache() { } void Replace() { m_ra.Replace(); } }; int main() { Cache<Random_ReplaceAlgorithm> cache; //模板实参 cache.Replace(); return 0; }
3、适配器模式
适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。它包括类适配器和对象适配器。
例:
![](https://images2017.cnblogs.com/blog/1039362/201708/1039362-20170814172520146-129703381.png)
//双端队列 class Deque { public: void push_back(int x) { cout<<"Deque push_back"<<endl; } void push_front(int x) { cout<<"Deque push_front"<<endl; } void pop_back() { cout<<"Deque pop_back"<<endl; } void pop_front() { cout<<"Deque pop_front"<<endl; } }; //顺序容器 class Sequence { public: virtual void push(int x) = 0; virtual void pop() = 0; }; //栈 class Stack: public Sequence { public: void push(int x) { deque.push_back(x); } void pop() { deque.pop_back(); } private: Deque deque; //双端队列 }; //队列 class Queue: public Sequence { public: void push(int x) { deque.push_back(x); } void pop() { deque.pop_front(); } private: Deque deque; //双端队列 }; int main() { Sequence *s1 = new Stack(); Sequence *s2 = new Queue(); s1->push(1); s1->pop(); s2->push(1); s2->pop(); delete s1; delete s2; return 0; }