//设计模式六大原则
/** 总原则:开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。
所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。
1、单一职责原则
:不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。
2、里氏替换原则(Liskov Substitution Principle)
:里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。
LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
里氏替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
3、依赖倒转原则(Dependence Inversion Principle)
:依赖倒转原则是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
4、接口隔离原则(Interface Segregation Principle)
:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
5、迪米特法则(最少知道原则)(Demeter Principle)
:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。
我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
6、合成复用原则(Composite Reuse Principle)
:原则是尽量首先使用组合/聚合的方式,而不是使用继承。
*/ /*================================<创建型模式>===============================*/
1、工厂方法模式(Factory)
/*----------------------------------------
模式功能:定义创建对象的接口,封装对象的创建。使得具体化类的工作延迟到子类中。
---------------------------------*/
#if 0
class Product
{
public:
virtual ~Product() {}
Product() {}
virtual void doAction() = 0;
};
class ConcreteProduct : public Product
{
public:
virtual ~ConcreteProduct() {}
ConcreteProduct() {}
void doAction()
{
printf_s("Factory mode ConcreteProduct to do what you want to do!\n");
}
};
class Factory {
public:
virtual ~Factory() {}
virtual Product* CreateProduct() = 0;
protected:
Factory() {}
};
class ConcreteFactory : public Factory {
public:
~ConcreteFactory() {}
ConcreteFactory() {}
Product* CreateProduct()
{
return new ConcreteProduct();
}
};
int main()
{
Factory* factory = new ConcreteFactory();
Product* product = factory->CreateProduct();
product->doAction();
system("pause");
return 0;
}
#endif
2、抽象工厂模式(AbstractFactory)
// 实际上,AbstractFactory模式是为创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式是为一类对象提供创建接口或延迟对象的创建到子类中实现。
#if 0
class AbstractProduct
{
public:
virtual ~AbstractProduct() {}
AbstractProduct() {}
virtual void doAction() = 0;
};
class ConcreteAbProduct : public AbstractProduct
{
public:
virtual ~ConcreteAbProduct() {}
ConcreteAbProduct() {}
void doAction()
{
printf_s("AbstractFactory mode ConcreteAbProduct to do what you want to do!\n");
}
};
// 抽象工厂
class AbstractFactory {
public:
virtual ~AbstractFactory() {}
virtual AbstractProduct* CreateProduct() = 0;
protected:
AbstractFactory() {}
};
class ConcreteAbFactory : public AbstractFactory {
public:
~ConcreteAbFactory() {}
ConcreteAbFactory() {}
AbstractProduct* CreateProduct()
{
return new ConcreteAbProduct();
}
};
int main()
{
AbstractFactory* factory = new ConcreteAbFactory();
AbstractProduct* product = factory->CreateProduct();
product->doAction();
system("pause");
return 0;
}
#endif
3、单例模式(Singleton)
/*
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
*/
4、建造者模式(Builder)
/**/
5、原型模式(Prototype)
/*
原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。
*//*================================<结构型模式>================================*/
1、装饰模式(Decorator)
/*-------------------------------------
指在不改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象来包裹一个真实的对象。
适用场景:装饰对象和真实对象有相同的接口,这样客户端就能以和真实对象相同的方式和装饰对象交互。
--------------------------------------*/
#if 0
class Component {
public:
virtual void Operation() = 0;
};
class ConcreteComponent :public Component {
public:
void Operation()
{
printf_s("Decorator mode to do what you want to do!\n");
}
};
class Decorator : public Component{
public:
Decorator(Component* component)
{
m_component = component;
}
~Decorator()
{
if (m_component)
delete m_component;
}
void Operation()
{
m_component->Operation();
}
protected:
Component* m_component;
};
class ConcreteDecorator : public Decorator
{
public:
ConcreteDecorator(Component* component):Decorator(component)
{}
private:
void Operation()
{
m_component->Operation();
}
};
int main()
{
Component* component = new ConcreteComponent();
Decorator* decorator = new ConcreteDecorator(component);
decorator->Operation();
system("pause");
return 0;
}
#endif
2、组合模式(Conposite)
#if 0
class Component
{
public:
Component() {}
virtual ~Component() {}
public:
virtual void Operation() = 0;
virtual void Add(const Component&)
{}
virtual void Remove(const Component&)
{}
virtual Component* GetChild(int index)
{
return 0;
}
};
class Composite : public Component
{
public:
Composite() {}
~Composite() {}
public:
void Operation()
{
vector<Component*>::iterator compIter = compVec.begin();
for (compIter; compIter != compVec.end(); compIter++)
{
(*compIter)->Operation();
}
}
void Add(Component* comp)
{
compVec.push_back(comp);
}
void Remove(Component* comp)
{
vector<Component*>::iterator compIter = compVec.begin();
for (compIter; compIter != compVec.end(); compIter++)
{
if (*compIter == comp)
{
compVec.erase(compIter);
break;
}
}
}
Component* GetChild(int index)
{
return compVec[index];
}
private:
vector<Component*> compVec;
};
class Left : public Component
{
public:
Left() {}
~Left() {}
public:
void Operation()
{
printf_s("Composite mode to do what you want to do!\n");
}
};
int main()
{
Left* left = new Left();
left->Operation();
Composite* composite = new Composite();
composite->Add(left);
composite->Operation();
Component* component = composite->GetChild(0);
component->Operation();
system("pause");
return 0;
}
#endif
3、代理模式(Proxy)
// 适用场景:当无法直接访问某个对象或不能直接引用另一个对象时,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现同样的接口。
/*----------------------------------------
解决问题:
1.创建开销大的对象时,如显示一幅大的图片,我们将这个创建的过程交给代理去完成,称之为虚代理(Virtual Proxy)
2.为网络上的对象创建一个局部的本地代理,比如要操作一个网络上的对象(网络性能不好的时候,问题尤其突出),我们将这个操作的过程交给一个代理去完成,称之为远程代理(Remote Proxy)
3.对对象进行控制访问时,有不同的造作权限,我们将这个工作交给一个代理去完成,称之为保护代理(Protection Proxy)
4.当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来,即智能引用(Smart Reference)
5.为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以使用这些结果,即Cache代理
-----------------------------------------*/
#if 0
// 抽象主题角色
class Subject {
public:
virtual ~Subject() {}
virtual void Request() = 0;
};
// 具体主题角色
class ConcreteSubject : public Subject {
public:
~ConcreteSubject() {}
void Request()
{
// TODO
printf_s("Proxy mode to do what you want to do!\n");
}
};
// 代理主题角色
class Proxy : public Subject {
public:
~Proxy()
{
if (m_subject)
delete m_subject;
}
Proxy(Subject* subject) {
m_subject = subject;
}
void before() {}
void after() {}
void Request()
{
before();
m_subject->Request();
after();
}
private:
Subject* m_subject;
};
int main()
{
Subject* subject = new RealSubject();
Proxy proxy(subject);
proxy.Request();
system("pause");
return 0;
}
#endif
4、适配器模式(Adapter):分为类适配器模式、对象适配器模式
/*----------------------------------------
适用场景:把一个类的接口变成客户端多期待的另一种接口,从而使原本接口不匹配而无法工作的两个类能够在一个工作。
-----------------------------------------*/
#if 0
// 目标主题角色
class Target {
public:
virtual ~Target() {}
virtual void Request() = 0;
};
// 被适配角色
class Adapted {
public:
~Adapted() {}
void SpecificRequest()
{
// TODO
printf_s("Adapted mode to do what you want to do!\n");
}
};
// 适配器(继承模式)
class Adapter1 : public Target, private Adapted {
public:
~Adapter1() {}
Adapter1() {}
void Request()
{
SpecificRequest();
}
};
// 适配器(组合模式)
class Adapter2 : public Target {
public:
~Adapter2()
{
if (m_adapted)
delete m_adaptee;
}
Adapter2(Adapted* adaptee)
{
m_adapted = adapted;
}
void Request()
{
m_adapted->SpecificRequest();
}
private:
Adapted* m_adapted;
};
int main()
{
//Target* target = new Adapter1();
Target* target = new Adapter2(new Adapted());
target->Request();
system("pause");
return 0;
}
#endif
5、桥接模式(Bridge)
#if 0
class AbstractionImp
{
public:
AbstractionImp() {}
virtual ~AbstractionImp() {}
virtual void Operator() = 0;
};
class ConcreteAbstractionImmp : public AbstractionImp
{
public:
ConcreteAbstractionImmp() {}
~ConcreteAbstractionImmp() {}
public:
void Operator()
{
printf_s("Bridge mode to do what you want to do!\n");
}
};
class Abstraction
{
public:
Abstraction() {}
virtual ~Abstraction() {}
virtual void Operator() = 0;
};
class RefinedAbstraction : public Abstraction
{
public:
RefinedAbstraction(AbstractionImp* absImp)
{
m_absImp = absImp;
}
~RefinedAbstraction()
{
if (m_absImp)
delete m_absImp;
}
public:
void Operator()
{
m_absImp->Operator();
}
private:
AbstractionImp* m_absImp;
};
int main()
{
AbstractionImp* absImp = new ConcreteAbstractionImmp();
Abstraction* abstract = new RefinedAbstraction(absImp);
abstract->Operator();
system("pause");
return 0;
}
#endif
6、外观模式(Facade)
/*------------------------------------------
外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度。
-------------------------------------------*/
#if 0
class SubSystem1
{
public:
SubSystem1() {}
~SubSystem1() {}
void Operator()
{
printf_s("Facade mode SubSystem1 to do what you want to do!\n");
}
};
class SubSystem2
{
public:
SubSystem2() {}
~SubSystem2() {}
void Operator()
{
printf_s("Facade mode SubSystem2 to do what you want to do!\n");
}
};
class Facade
{
public:
Facade()
{
m_sub1 = new SubSystem1();
m_sub2 = new SubSystem2();
}
~Facade()
{
delete m_sub1;
m_sub1 = nullptr;
delete m_sub2;
m_sub2 = nullptr;
}
void OperationWrapper()
{
m_sub1->Operator();
m_sub2->Operator();
}
private:
SubSystem1* m_sub1;
SubSystem2* m_sub2;
};
int main()
{
Facade* facade = new Facade();
facade->OperationWrapper();
return 0;
}
#endif
7、享元模式(Flyweight)
/*
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。
*/
/*==================================<行为型模式>================================*/
1、观察者模式(Observer)
/*--------------------------------------
解决问题: 建立一个一(Subject)对多(Observer)的依赖关系,并且做到一变化时依赖其的多个对象也能够同步变化。
---------------------------------------*/
#if 0
class Subject;
class Observer
{
public:
Observer() {}
virtual ~Observer() {}
public:
virtual void Update(Subject* sub) = 0;
};
// 具体观察者(订阅者)
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(Subject* sub)
{
m_sub = sub;
}
~ConcreteObserver()
{
if (m_sub)
delete m_sub;
}
public:
void Update(Subject* sub)
{
printf_s("Observer mode to do what you want to do!\n");
}
private:
Subject* m_sub;
};
class Subject
{
public:
Subject() {}
virtual ~Subject() {}
public:
virtual void Attach(Observer* obv) = 0;
virtual void Detach(Observer* obv) = 0;
virtual void Notify() = 0;
virtual void SetState(int state) = 0;
virtual int GetState() = 0;
};
// 具体目标(发布者)
class ConcreteSubject : public Subject
{
public:
ConcreteSubject() {}
~ConcreteSubject() {}
public:
void Attach(Observer* obv)
{
observerList.push_front(obv);
}
void Detach(Observer* obv)
{
observerList.remove(obv);
}
void Notify()
{
list<Observer*>::iterator itr = observerList.begin();
for (itr; itr != observerList.end(); itr++)
{
(*itr)->Update(this);
}
}
void SetState(int state)
{
m_state = state;
}
int GetState()
{
return m_state;
}
private:
list<Observer*> observerList;
int m_state;
};
int main()
{
Subject* sub = new ConcreteSubject();
Observer* obv = new ConcreteObserver(sub);
sub->Attach(obv);
sub->Notify();
system("pause");
return 0;
}
#endif
2、状态模式(State)
#if 0
class Context;
class State
{
public:
State() {}
virtual ~State() {}
protected:
virtual void ChangeState(Context* con, State* sta)
{
con->ChangeState(sta);
}
public:
virtual void OperatorInterface(Context* con) = 0;
virtual void OperatorChangeState(Context* con) = 0;
};
class ConcreteStateA : public State
{
public:
ConcreteStateA() {}
~ConcreteStateA() {}
public:
void OperatorInterface(Context* con)
{
}
void OperatorChangeState(Context* con)
{
OperatorInterface(con);
this->ChangeState(con, NULL);
}
};
class ConcreteStateB
{
public:
ConcreteStateB() {}
~ConcreteStateB() {}
public:
void OperatorInterface(Context* con)
{
}
void OperatorChangeState(Context* con)
{
OperatorInterface(con);
}
};
class Context
{
public:
Context() {}
virtual ~Context() {}
public:
void ChangeState(State* state)
{
m_state = state;
}
void OperatorInterface(State* sta)
{
sta->OperatorInterface(this);
}
void OperatorChangeState(State* sta)
{
sta->OperatorChangeState(this);
}
private:
State* m_state;
};
int main()
{
return 0;
}
#endif
3、策略模式(Strategy)
/*----------------------------------------
Strategy模式和Template模式要解决的问题是类似的,都是为了给业务逻辑的具体实现和抽象接口之间解耦。
Strategy模式将逻辑(算法)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给组合对象实现。
State模式也有类似的功能。
-----------------------------------------*/
#if 0
class Strategy
{
public:
virtual ~Strategy() {}
Strategy() {}
virtual void Algorithm() = 0;
};
class ConcreteStrategyA : public Strategy
{
public:
~ConcreteStrategyA() {}
ConcreteStrategyA() {}
void Algorithm() // 具体实现
{
printf_s("Strategy mode ConcreteStrategyA to do what you want to do!\n");
}
};
class ConcreteStrategyB : public Strategy
{
public:
~ConcreteStrategyB() {}
ConcreteStrategyB() {}
void Algorithm()
{
printf_s("Strategy mode ConcreteStrategyB to do what you want to do!\n");
}
};
// 依赖策略
class Context {
public:
Context(Strategy* strategy)
{
m_strategy = strategy;
}
~Context()
{
if (m_strategy)
delete m_strategy;
}
void doAction()
{
m_strategy->Algorithm();
}
private:
Strategy* m_strategy;
};
int main()
{
Strategy* strategy = new ConcreteStrategyA();
Context* context = new Context(strategy);
context->doAction();
system("pause");
return 0;
}
#endif
4、模板方法模式(Template)
/*
指:一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用。
*/
5、迭代器模式(Iterator)
/*
迭代器模式就是顺序访问聚集中的对象,这句话包含两层意思:一是需要遍历的对象,即聚集对象,二是迭代器对象,用于对聚集对象进行遍历访问。
*/
6、责任链模式(Chain of Responsibility)
/*
责任链模式:有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。
但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。
*/
7、命令模式(Command)
/**/
8、备忘录模式(Memento)
/*
主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象。
通俗的讲下:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C呢,就是一个用来存储备忘录的,且只能存储,不能修改等操作。
*/
9、访问者模式(Visitor)
/*
访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。
因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。
简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。
*/
10、中介者模式(Mediator)
/*
中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改。
如果使用中介者模式,只需关心和Mediator类的关系,具体类类之间的关系及调度交给Mediator就行,这有点像spring容器的作用。
*/
11、解释器模式(Interpreter)
/**/