创建型
分类原因
创建型设计模式抽象了实例化过程。
-
它们帮助一个系统独立于 一些对象
-
创建它的对象
-
组合它的对象
-
表示它的对象
-
-
这些创建型设计模式,有两个不断出现的主旋律。封装该系统内:
- 使用哪些具体的类
- 这些类的实例是如何被创建和被放在一起的。
-
创建型模式,给予了灵活性
- 什么 被创建,谁 创建了它,它怎么 被创建,何时被创建
单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式
对象创建 | |
---|---|
Factory 模式 | 被实例化的子类 |
AbstactFactory 模式 | 产品对象家族 |
Prototype 模式 | 针对被实例化的类 |
Builder 模式 | 如何创建一个组合对象 |
对象创建&对象性能 | |
Singleton 模式 | 针对一个类的唯一实例 |
单例模式
用途
实现单例模式的步骤:
1、构造函数私有化
2、增加静态私有的当前类的指针变量
3、提供静态对外接口,可以让用户获得单例对象
饿汉式
饿汉式:
- 还没有使用该单例对象,该单例对象就已经被加载到内存了
- 在对象过多时会造成内存浪费
需要在main函数前,为单例对象赋值。
shell
instance created hungryly.
process started !
waiting done.
got instance
m property is 2
process exit
cpp
#include <cstdio>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
class Singleton_hungry{
private:
int mProp = 0;
Singleton_hungry(int intParam = 1):mProp(intParam) {
printf("instance created hungryly.\n");
};
~Singleton_hungry() {
if (mInstance) {
delete mInstance;
}
printf("instance deleted.\n");
}
public:
static Singleton_hungry* mInstance;
static Singleton_hungry* getInstance() {
printf("got instance\n");
if (mInstance) {
return mInstance;
}
mInstance = new Singleton_hungry;
return mInstance;
}
void do_print() {
printf("m property is %d \n", mProp);
}
};
//以下语句需要在main函数运行前执行
Singleton_hungry* Singleton_hungry::mInstance = new Singleton_hungry(2);
int main() {
Singleton_hungry* mHungryPtr;
printf("process started !\n");
std::this_thread::sleep_for(std::chrono::milliseconds(400));
printf("waiting done.\n");
mHungryPtr = Singleton_hungry::getInstance();
mHungryPtr->do_print();
std::this_thread::sleep_for(std::chrono::milliseconds(400));
printf("process exit\n");
return 1;
}
懒汉式
懒汉式:
- 避免了内存浪费
- 引入新问题:线程不安全------可以通过互斥量来解决。线程不安全的问题。
cpp
#include <cstdio>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
class Singleton_hungry{
private:
int mProp = 0;
Singleton_hungry(int intParam = 1):mProp(intParam) {
printf("instance created hungryly.\n");
};
~Singleton_hungry() {
if (mInstance) {
delete mInstance;
}
printf("instance deleted.\n");
}
public:
static Singleton_hungry* mInstance;
static Singleton_hungry* getInstance() {
printf("got instance\n");
if (mInstance) {
return mInstance;
}
mInstance = new Singleton_hungry;
return mInstance;
}
void do_print() {
printf("m property is %d \n", mProp);
}
};
//以下语句需要在main函数运行前执行
Singleton_hungry* Singleton_hungry::mInstance = new Singleton_hungry(2);
int main() {
Singleton_hungry* mHungryPtr;
Singleton_hungry* mHungryPtr2;
printf("process started !\n");
std::this_thread::sleep_for(std::chrono::milliseconds(400));
printf("waiting done.\n");
mHungryPtr = Singleton_hungry::getInstance();
mHungryPtr2 = Singleton_hungry::getInstance();
if (mHungryPtr != mHungryPtr2) {
printf("fail to get instance \n");
} else {
printf("get same instance\n");
}
std::this_thread::sleep_for(std::chrono::milliseconds(400));
printf("process exit\n");
return 1;
}
工厂模式
cpp
#include <cstdio>
#include <iostream>
using namespace std;
class AbstractProduct {
public:
virtual void do_something() = 0;
};
class ConcreteProductA_1 : public AbstractProduct {
public:
ConcreteProductA_1() {
printf("ConcreteProductA_1 created!\n");
}
void do_something() {
printf("ConcreteProductA_1 do something.\n");
}
};
class ConcreteProductA_2 : public AbstractProduct {
public:
ConcreteProductA_2() {
printf("ConcreteProductA_2 created!\n");
}
void do_something() {
printf("ConcreteProductA_2 do something.\n");
}
};
class ConcreteFactory {
public:
AbstractProduct* createProduct(int type){
AbstractProduct* mProduct = nullptr;
switch (type) {
case 1:
mProduct = dynamic_cast<AbstractProduct*>(new ConcreteProductA_1);
break;
case 2:
mProduct = dynamic_cast<AbstractProduct*>(new ConcreteProductA_2);
break;
default:
printf("unkown product type");
}
return mProduct;
}
};
int main() {
ConcreteFactory* mFactory = new ConcreteFactory();
AbstractProduct* mProduct = mFactory->createProduct(1);
mProduct->do_something();
return 0;
}
抽象工厂
cpp
#include <cstdio>
class AbstractProduct {
public:
virtual void do_something() = 0;
virtual ~AbstractProduct() {
printf("AbstractProduct 虚析构\n");
}
};
class AbstractProductA : public AbstractProduct {
public:
// virtual void do_something() = 0;
virtual void do_something_special_A() = 0;
virtual ~AbstractProductA() {
printf("AbstractProductA 虚析构\n");
}
};
class AbstractProductB : public AbstractProduct {
public:
virtual void do_something_special_B() = 0;
virtual ~AbstractProductB() {
printf("AbstractProductB 虚析构\n");
}
};
class ConcreteProductA : public AbstractProductA {
public:
void do_something() {
printf("ConcreteProductA do_something\n");
}
void do_something_special_A() {
printf("ConcreteProductA do_something_special_A\n");
}
};
class ConcreteProductB : public AbstractProductB {
public:
void do_something() {
printf("ConcreteProductB do_something\n");
}
void do_something_special_A() {
printf("ConcreteProductB do_something_special_B\n");
}
};
class AbstractFactory {
public:
virtual AbstractProduct* createProduct(int type) = 0;
virtual ~AbstractFactory() {
printf("AbstractFactory 虚析构\n");
}
};
class ConcreteFactoryA : public AbstractFactory {
public:
AbstractProduct* createProduct(int type) {
AbstractProduct* mProduct = nullptr;
mProduct = dynamic_cast<AbstractProduct*>(new ConcreteProductA);
return mProduct;
}
};
int main() {
AbstractFactory* mFactory = nullptr;
AbstractProduct* mProduct = nullptr;
mFactory = new ConcreteFactoryA();
mProduct = mFactory->createProduct(1);
mProduct->do_something();
delete mProduct;
delete mFactory;
// mFactory = new ConcreteFactoryB();
return 1;
}
建造者模式
概念
当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要要复杂对象的创建过程和这个对象的表示(展示)分离开来,这样做的好处就是通过一步步的进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。
- Builder 模式的关键是其中的 Director对象并不直接返回对象,而是通过一步步(BuildPartA,BuildPartB,BuildPartC)来一步步进行对象的创建。
- Builder 模式的示例代码中,BuildPart 的参数是通过客户程序员传入的,这里使用"user-defined"代替,实际的可在 Construct 方法中传入这 3 个参数,这样就可以得到不同的细微差别的复杂对象了。
Builder 模式和 AbstractFactory 模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是Builder 模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说 Builder 模式中对象不是直接返回的。而在 AbstractFactory 模式中对象是直接返回的,AbstractFactory 模式强调的是为创建多个相互依赖的对象提供一个同一的接口。
code
cpp
#include <cstdio>
#include <iostream>
class Product {
public:
std::string name;
int level;
void do_print() {
printf("name = %s, level = %d \n", name.c_str(), level);
}
};
class Builder {
public:
Product* mProduct = nullptr;
void set_product(Product* product) {
this->mProduct = product;
}
Product* get_product() {
return this->mProduct;
}
void build_name(std::string name) {
if (this->mProduct)
this->mProduct->name = name;
}
void build_level(int level) {
if (this->mProduct)
this->mProduct->level = level;
}
};
class Director {
public:
Builder* mBuilder = nullptr;
void set_builder(Builder* builder) {
this->mBuilder = builder;
}
void do_build(std::string name, int level) {
Product* product = this->mBuilder->get_product();
this->mBuilder->build_name(name);
this->mBuilder->build_level(level);
}
};
int main() {
Product* mProduct = new Product;
Builder* mBuilder = new Builder;
Director* mDirector = new Director;
mBuilder->set_product(mProduct);
mDirector->set_builder(mBuilder);
mDirector->do_build("张三", 100);
mProduct->do_print();
return 0;
}
原型模式
Prototype 模式(原型模式)
定义:Prototype 模式也正是提供了自我复制的功能,就是说新对象的创建可以通过已有对象进行创建。在 C++中拷贝构造函数(Copy Constructor)曾经是很对程序员的噩梦,拷贝又分为浅拷贝和深拷贝
-
浅拷贝:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
-
深拷贝:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。clone明显是深复制,clone出来的对象是是不能去影响原型对象的
Prototype 模式提供了一个通过已存在对象进行新对象创建的接口(Clone),Clone接口在 C++中我们将通过拷贝构造函数实现。