设计模式(学习笔记day01)

1.设计模式
设计模式是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结。*(套路)
设计模式的目的:为了代码可重用性,让代码更容易被他人理解,保证代码的可靠性。设计模式使代码编写真正工程化,设计模式是软件工程的基石脉络,如同大厦的结构一样。

一、单例模式

一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务器进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

单例模式有两种实现模式:饿汉模式和懒汉模式

a)、饿汉模式
就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。

饿汉模式
优点:简单
缺点:可能会导致进程启动慢,且如果有多个单例
类对象实例启动顺序不确定
class Singleton{
public:
	static Singleton* GetInstance()
	{
		return &m_instance;
	}
private:
	//构造函数私有
	Singleton(){};

	//c++98 防拷贝
	Singleton(Singleton const&);
	Singleton& operator=(Singleton const&);

	//or
	//c++11
	/*Singleton(Singleton const&) = delete;
	Singleton& operator=(Singleton const&) = delete;*/

	static Singleton m_instance;
};

Singleton Singleton::m_instance;//在程序入口之前就完成单例对象的初始化

如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提供相应速度更好。



b)、懒汉模式
如果单例对象构造释放耗时或者占用很大资源,比如加载插件,初始化连接网络,读取文件等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始进行初始化,就会导致程序启动时非常缓慢,所以这种情况下使用**懒汉模式(延迟加载)**更好。

懒汉模式
优点:第一次使用实例对象时,创建对象。进程启动无负载,多个单例实例启动顺序可以自由控制
缺点:复杂
#include<iostream>
#include<mutex>
#include<thread>
using namespace std;

class Singleton{
public:
	static Singleton* GetInstance()
	{
		//注意这里一定要使用doule—check的方式加锁,才能保证效率和线程的安全
		if (nullptr == m_pInstance)
		{
//防止死锁,如果抛出异常就会造成死锁;
			m_mtx.lock();
			if (nullptr == m_pInstance)
			{
				m_pInstance = new Singleton();
			}
			m_mtx.unlock();
		}
		return m_pInstance;
	}
	//实现一个内嵌垃圾回收类
	class CGarbo{
	public:
		~CGarbo()
		{
			if (Singleton::m_pInstance)
			{
				delete Singleton::m_pInstance;
			}
		}
	};
	
	//定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
	static CGarbo Garbo;

private:
	//构造函数私有
	Singleton(){};

	//防拷贝
	Singleton(const Singleton&);
	Singleton& operator=(Singleton const&);

	static Singleton* m_pInstance;//单例对象指针
	static mutex m_mtx; //互斥锁
};

Singleton* Singleton::m_pInstance = nullptr;
Singleton::CGarbo Garbo;
mutex Singleton::m_mtx;

二、简单工厂模式

a)、为什么要使用工厂模式
 程序更规范有条理,当我们创建实例对象时,如果不仅仅做赋值这样简单的事情,而是有一大段逻辑,那这个时候我们要将所有的初始化逻辑都写在构造函数中吗? 显然,这样使得代码很难看;
降低耦合度,提高可阅读性。面向对象的基本思想封装告诉我们,我们尽量将长的代码进行"切割",再将每一个小逻辑都"封装"起来,这样可以降低耦合度,修改的时候也可以直奔错误段落。


1、简介

简单工厂模式是属于创建型模式,又叫做静态工厂方法(static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出来哪一种产品类的实例。

2、特点

是由一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类继承自一个父类或接口)的实例;

需要在工厂类中作出判断,在创建产品的时候,指定响应产品创造。

 

3、举个例子:

假设有一个工厂,他能生产出A、B两种产品。当客户需要产品的时候一定要告诉工厂是哪种产品,是A还是B。当新增加一种新产品的时候,那么就要去修改工厂的类。 

 

4、应用说明:

一个工厂,多个产品。产品需要有一个虚基类。通过传入参数,生成具体产品对象,并利用基类指针指向此对象。

程序案例:
#include <iostream>
 
using namespace std;
 
//类方法—生产的产品
class Product
{
public:
    virtual void show()=0;
 
}
 
class  Product_A :public Product   //产品A
{
 
public:
    void show()
    {
 
    cout<<"Product_A"<<endl;
 
    }
 
};
 
class Product_B : public Product   //产品B
{
 
public:
    void show()
    {
        cout<<"Product_B"<<endl;
 
    }
 
};
 
//工厂
 
class Factory                //只有一家工厂,可以生产不同的产品
{
public:
    Product* Create(int i)
    {
        switch(i)
        {
            case 1:                      //生产产品A
                return new Prodent_A;
                break;
 
            case 2:                       //生产产品B
                return new Product_B;
                break;
            
            default:
                break;
        }
 
    }
 
};
 
int main()
{
    Factory *factoty = new Factory();   //实例化--工厂对象
    factoty->Create(1)->show();          //指定生产A产品
    factoty->Create(2)->show();          //指定生产B产品
    system("pause");
    return 0;
 
}
5、缺点:

每次新增一个类时,都需要改变工厂函数,破坏了封装性;(如果生产厂家需要新增一个产品,那么工厂函数Factory就需要跟着改变,所以上面的工厂模式违背了开放封闭原则;)

补:开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。

三、抽象工厂模式

1、简介
多个工厂,多个产品,并且每个产品可以包含多个型号。此时工厂和产品都是通过虚基类的方式构建。每一个工厂类可以生产同一个产品的多个型号。

2、特点
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

3、举个例子:
假如我们A产品中有A1和A2两种型号的厂品,B产品中有B1和B2两种型号的厂品,那怎么办,上面两种工厂模式就不能解决了。这个时候抽象工厂模式就登场了。还是开设两家工厂,工厂A负责生产A1 、A2型号产品,B工厂负责生产B1、B2型号的产品。

4、应用说明:
#include <iostream>    
using namespace std;  
  
//定义抽象类  
class product1  
{  
public:  
    virtual void show() = 0;  
};  
  
//定义具体类  
class product_A1 :public product1  
{  
public:  
    void show(){ cout << "product A1" << endl; }  
};  
  
class product_B1 :public product1  
{  
public:  
    void show(){ cout << "product B1" << endl; }  
};  
  
//定义抽象类  
class product2  
{  
public:  
    virtual void show() = 0;  
};  
  
//定义具体类  
class product_A2 :public product2  
{  
public:  
    void show(){ cout << "product A2" << endl; }  
};  
  
class product_B2 :public product2  
{  
public:  
    void show(){ cout << "product B2" << endl; }  
};  
  
  
class Factory                //工厂
{  
public:  
    virtual product1 *creat1() = 0;  
    virtual product2 *creat2() = 0;  
};  
  
class FactoryA                    //工厂A 可以有多个函数方法(产品)
{  
public:  
    product1 *creat1(){ return new product_A1(); }  
    product2 *creat2(){ return new product_A2(); }  
};  
  
class FactoryB                   //工厂B 可以有多个函数方法(产品)
{  
public:  
    product1 *creat1(){ return new product_B1(); }  
    product2 *creat2(){ return new product_B2(); }  
};  
  
int main()  
{  
    FactoryA *factoryA = new FactoryA();     //实例化--工厂对象A
    factoryA->creat1()->show();              //工厂A 调用函数(生产产品1)
    factoryA->creat2()->show();              //工厂A 调用函数(生产产品2)
  
    FactoryB *factoryB = new FactoryB();     //实例化--工厂对象B
    factoryB->creat1()->show();              //工厂B 调用函数(生产产品1)
    factoryB->creat2()->show();              //工厂B 调用函数(生产产品2)
  
    return 0;  
}
5、优点:
易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这样就使得改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可使用不同的产品配置。

让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂实现分离,不会出现在客户代码中。

6、缺点:
增加新的产品时需要改动多处代码。

四、工厂方法模式

1、简介
多个工厂,多个产品,每个产品对应于一个工厂。此时工厂和产品都是通过虚基类的方式构建。

2、特点
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
当增加一个新产品时,同时增加一个新工厂。增加新工厂属于扩展,不会修改以前工厂类和产品类的任何代码。可以看过多个独立的简单工厂模式构成了工厂方法模式。
 
3、举个例子:
假设现在有A、B两种产品,那么久开两个工厂。工厂A负责生产A产品,工厂B负责生产B种产品。这时候客户不需要告诉共产生产哪种产品了,只需要告诉共产生产就可以了。

4、应用说明:
 把简单工厂模式中的工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。

5、程序案例:

#include "stdafx.h"
#include<iostream>
 
using namespace std;
 
//类方法—生产的产品
class Product
{
public:
    virtual void show() = 0;  
};
 
class Product_A : public Product    //产品A
{
public:
    void show()
    {
        cout << "Product_A" << endl;
    }
};
 
class Product_B : public Product   //产品B
{
public:
    void show()
    {
        cout << "Product_B" << endl;
    }
};
 
class Factory          //工厂
{
public:
    virtual Product* create() = 0;
};
 
class Factory_A : public Factory  //工厂A 只有一个函数方法(产品)
{
public:
    Product* create()
    {
        return new Product_A;
    }
};
 
class Factory_B : public Factory  //工厂B 只有一个函数方法(产品)
{
public:
    Product* create()
    {
        return new Product_B;
    }
};
 
int main()
{
    Factory_A* productA = new Factory_A();  //实例化--工厂对象A
    Factory_B* productB = new Factory_B();  //实例化--工厂对象B
 
    productA->create()->show();         //工厂A 调用函数(生产产品)
    productB->create()->show();         //工厂B 调用函数(生产产品)
    system("pause");
    return 0;
}

6、缺点:
每增加一个新的产品,就需要增加一个新的工厂

学习笔记,记录学习的进度,写得不好,希望大家多指点指点,一起进步,thank you!

猜你喜欢

转载自blog.csdn.net/m0_43458204/article/details/106333813