创建型模式提供了创建对象的机制, 能够提升已有代码的灵活性和可复用性。
Singleton is a creational design pattern that lets you ensure that
a class has only one instance,
while providing a global access point to this instance.
/**
* The Singleton class defines the `GetInstance` method that serves as an
* alternative to constructor and lets clients access the same instance of this
* class over and over.
*/
class Singleton
{
/**
* The Singleton‘s constructor/destructor should always be private to
* prevent direct construction/desctruction calls with the `new`/`delete`
* operator.
*/
private:
static Singleton * pinstance_;
static std::mutex mutex_;
protected:
Singleton(const std::string value): value_(value)
{
}
~Singleton() {}
std::string value_;
public:
/**
* Singletons should not be cloneable.
*/
Singleton(Singleton &other) = delete;
/**
* Singletons should not be assignable.
*/
void operator=(const Singleton &) = delete;
/**
* This is the static method that controls the access to the singleton
* instance. On the first run, it creates a singleton object and places it
* into the static field. On subsequent runs, it returns the client existing
* object stored in the static field.
*/
static Singleton *GetInstance(const std::string& value);
/**
* Finally, any singleton should define some business logic, which can be
* executed on its instance.
*/
void SomeBusinessLogic()
{
// ...
}
std::string value() const{
return value_;
}
};
/**
* Static methods should be defined outside the class.
*/
Singleton* Singleton::pinstance_{nullptr};
std::mutex Singleton::mutex_;
/**
* The first time we call GetInstance we will lock the storage location
* and then we make sure again that the variable is null and then we
* set the value. RU:
*/
Singleton *Singleton::GetInstance(const std::string& value)
{
std::lock_guard<std::mutex> lock(mutex_);
if (pinstance_ == nullptr)
{
pinstance_ = new Singleton(value);
}
return pinstance_;
}
适用场景:
· 相同的方法,不同的执行顺序,产生不同的结果。
· 多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
· 产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
· 初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
重写拷贝函数
把类或对象结合在一起形成一个更大的结构。一般是解决不同的类之间有不同关系的情况。
包含角色有目标接口,适配者类,适配器类
适配器类通过继承或引用适配者的对象,把适配者接口转换成目标接口
class Target {
public:
virtual ~Target() = default;
virtual std::string Request() const {
return "Target: The default target‘s behavior.";
}
};
class Adaptee {
public:
std::string SpecificRequest() const {
return ".eetpadA eht fo roivaheb laicepS";
}
};
class Adapter : public Target {
private:
Adaptee *adaptee_;
public:
Adapter(Adaptee *adaptee) : adaptee_(adaptee) {}
std::string Request() const override {
std::string to_reverse = this->adaptee_->SpecificRequest();
std::reverse(to_reverse.begin(), to_reverse.end());
return "Adapter: (TRANSLATED) " + to_reverse;
}
};
void ClientCode(const Target *target) {
std::cout << target->Request();
}
例,形状+颜色可以组合成平方级数的类,更好的做法是将其中一个(如颜色)分离成接口(setcolor())。
树形结构,管理员(非叶节点)与职员(叶节点)
在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
包含以下角色:
1.抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
2.具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
3.抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
4.具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
采用了装饰模式就只需要为每个装饰品生成一个装饰类即可,所以说就增加对象功能来说,装饰模式比生成子类实现更为灵活。
class Component {
public:
virtual ~Component() {}
virtual std::string Operation() const = 0;
};
class ConcreteComponent : public Component {
public:
std::string Operation() const override {
return "ConcreteComponent";
}
};
class Decorator : public Component {
protected:
Component* component_;
public:
Decorator(Component* component) : component_(component) {
}
std::string Operation() const override {
return this->component_->Operation();
}
};
class ConcreteDecoratorA : public Decorator {
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
}
};
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
}
};
外观模式最简单,它使得两种不同的类不用直接交互,而是通过一个中间件——也就是外观类——间接交互。外观类中只需要暴露简洁的接口,隐藏内部的细节,所以说白了就是封装的思想。
// 外观角色, 封装了三个子系统的方法
class Facade {
public:
void method() {
obj1->method1();
obj2->method2();
obj3->method3();
}
private:
SubSystem01 *obj1 = new SubSystem01();
SubSystem02 *obj2 = new SubSystem02();
SubSystem03 *obj3 = new SubSystem03();
};
当系统中多处需要同一组信息时,可以把这些信息封装到一个对象中,然后对该对象进行缓存,这样,一个对象就可以提供给多出需要使用的地方,避免大量同一对象的多次创建,降低大量内存空间的消耗。
享元模式其实是工厂方法模式的一个改进机制,享元模式同样要求创建一个或一组对象,并且就是通过工厂方法模式生成对象的,只不过享元模式为工厂方法模式增加了缓存这一功能。
1.抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
2.真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
3.代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
类和对象如何交互,及划分责任和算法。
父类定义模板方法以及具体的各个方法;子类重写各个方法。
类似状态机,为每个状态实现一个类
class Handler {
public:
virtual Handler *SetNext(Handler *handler) = 0;
virtual std::string Handle(std::string request) = 0;
};
class AbstractHandler : public Handler {
private:
Handler *next_handler_;
public:
AbstractHandler() : next_handler_(nullptr) {
}
Handler *SetNext(Handler *handler) override {
this->next_handler_ = handler;
return handler;
}
std::string Handle(std::string request) override {
if (this->next_handler_) {
return this->next_handler_->Handle(request);
}
return {};
}
};
/**
* All Concrete Handlers either handle a request or pass it to the next handler
* in the chain.
*/
class MonkeyHandler : public AbstractHandler {
public:
std::string Handle(std::string request) override {
if (request == "Banana") {
return "Monkey: I‘ll eat the " + request + ".\n";
} else {
return AbstractHandler::Handle(request);
}
}
};
不常用,暂忽略
中介者会逐渐变庞大,演变成上帝对象。
策略模式定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。策略模式用来解耦策略的定义、创建、使用。实际上,一个完整的策略模式就是由这三个部分组成的。
最常见的应用场景是,利用它来避免冗长的if-else或switch分支判断。
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。
访问者模式建议将新行为放入一个名为访问者的独立类中, 而不是试图将其整合到已有类中。
不常用。
原文:https://www.cnblogs.com/dirge/p/14656085.html