1.工厂模式
①简单工厂模式:简单工厂模式是由一个工厂对象根据收到的消息决定要创建哪一个类的对象实例,一般需要switch或if进行类型选择;工厂类创建的对象比较少,客户只需要传入工厂类参数,对于如何创建对象不关心;比如有一个手机工厂,可以加工出苹果手机和华为手机,客户给需求说要什么类型的手机,工厂就可以加工出那种型号的手机
//工厂加工的一般是一类产品,因此不同的手机继承自一个基类Phone
class Phone {
public:
Phone() {};
virtual void make() = 0;
//virtual void make() { cout << "生产一台手机"; };
};
//Iphone类
class Iphone :public Phone
{
public:
Iphone() {}
void make() { cout << "生产一台苹果手机"; }
};
//Honor类
class Honor : public Phone
{
public:
Honor() {}
void make() { cout << "生产一台荣耀手机"; }
};
//加工手机的工厂类
class PhoneFactory {
public:
PhoneFactory() {};
Phone* makephone(string s) {
if (s == "honor")
return new Honor();
else return new Iphone();
}
};
void main()
{
//工厂类的函数makephone,根据传入参数后生成不同的对象
PhoneFactory* factory = new PhoneFactory;
Phone* honor = factory->makephone("honor");
honor->make();
Phone* iphone = factory->makephone("apple");
iphone->make();
}
②工厂方法模式:定义一个创建对象的工厂接口,让工厂的子类决定实例化哪一个类,将实际创建工作推迟到子类当中。
//首先关于手机还是那三个类,此时将工厂类设为基类,添加了两个工厂子类
class AbstractFactory{
pubilc:
AbstractFactory(){}
virtual Phone* make_phone() = 0;
};
//生产荣耀手机的车间
class HonorFactory : public AbstractFactory{
pubilc:
HonorFactory(){}
Phone* make_phone(){return new Honor();}
};
//生产苹果手机的车间
class IphoneFactory : public AbstractFactory{
pubilc:
IphoneFactory(){}
Phone* make_phone(){return new Iphone();}
};
void main()
{
AbstractFactory* honor_factor=new HonorFactory();
AbstractFactory* iphone_factor=new IphoneFactory();
Phone* honoe=honor_factory->make_phone;
Phone*iphone=iphone_factory->make_phone;
}
2. 单例模式
饿汉式
class Singleton {
private:
Singleton(){ };
Singleton(Singleton&) { };
Singleton& operator = (const Singleton&) { };
static Singleton* instance;
public:
static Singleton* getInestance() { return instance; };
};
Singleton* Singleton::instance = new Singleton();
懒汉式
class Singleton {
private:
Singleton(){ };
Singleton(Singleton&) { };
Singleton& operator = (const Singleton&) { };
static Singleton* instance;
public:
~Singleton(){
delete ;
}
static Singleton* getInestance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
Singleton* Singleton::instance = nullptr;
存在两个问题:
- 多线程竞态会出现构造多个对象的情况
- 内存泄漏问题,程序将不会自动调用析构函数
双重校验锁+智能指针
class Singleton {
private:
Singleton() { cout << "constructor"<<endl; };
Singleton(Singleton&) { };
Singleton& operator = (const Singleton&) { };
static mutex mu;
static shared_ptr<Singleton>instance;
public:
~Singleton() { cout << "destructor"<<endl; };
static shared_ptr<Singleton> getInestance() {
if (instance == nullptr) {
lock_guard<mutex>lk(mu);
if (instance == nullptr) {
instance = shared_ptr<Singleton>(new Singleton());
}
}
return instance;
}
};
shared_ptr<Singleton> Singleton::instance = nullptr;
mutex Singleton::mu;
双重锁的缺陷
static shared_ptr<Singleton> getInestance() {
if (instance == nullptr) {
lock_guard<mutex>lk(mu);
if (instance == nullptr) {
instance = shared_ptr<Singleton>(new Singleton());
}
}
return instance;
}
线程A加锁进入构造阶段时,理论上应该依次执行以下三个步骤:①分配空间②调用构造函数③指针指向该内存区域。但是由于CPU指令优化,可能会首先为指针分配空间而未调用构造函数,如果此时线程B调用getInstance函数,由于指针已经分配了空间会直接返回,此时指针所指对象并未初始化,进行访问将出现不可预料的结果。
局部静态对象(C++11可用)
class Singleton {
private:
Singleton() {};
Singleton(Singleton&) {};
Singleton& operator = (const Singleton&) {};
public:
static Singleton* getInestance() {
static Singleton instance;
return &instance;
}
};