【C++】设计模式

                  设计模式三大类:

设计模式的基本原则

一、创建型模式

(1)单例模式:

(2)简单工厂模式

         (3)工厂模式

(4)抽象工厂模

         (5)建造者模式

二、结构型模式

         (1)代理模式

(2)装饰模式

(3)适配器模式

(4)桥接模式

(5)外观模式

(6)享元模式

三、行为型模式

(1)观察者模式


 

设计模式三大类:

  • 创建型模式
  • 结构型模式
  • 行为型模式

 

设计模式的基本原则

  • 开放-封闭原则(开闭原则):模块在扩展性方面应该是开放的,在更改性方面应该是封闭的(核心:对抽象编程,不对具体编程)
  • 依赖倒置原则:上层模块不应该依赖于下层模块,他们共同依赖于一个抽象(父类不依赖子类,他们都依赖于抽象类)
  • 单一职责原则:避免相同的职责分散到不同的类中,避免一个类承担太多职责(减少类的耦合,提高类的复用)
  • 接口隔离原则:使用多个专门的接口代替单个接口(每个接口服务于一个子模块)
    1、一个类对另一个类的依赖性应当建立在最小的接口上
    2、客户端程序不应该依赖它不需要的接口方法

     

  • 替换原则:子类型必须能够替换他们的父类型,并出现在父类能够出现的任何地方
    1、父类的方法都要在子类中实现或重写,并且派生类只实现其抽象类中声明的方法,不应该写出多余的方法定义或实现
    2、在客户端程序中只应该使用父类对象而不是直接使用子类对象,这样可以实现运行期间的绑定

     

 

 

一、创建型模式

(1)单例模式

使用单例模式可以保证一个类只生成唯一的实例对象(在整个程序空间中,该类只存在一个实例对象)

单例模式主要解决一个全局使用的类频繁的创建和销毁的问题。单例模式下可以确保某一个类只有一个实例

“保证一个类只有一个实例存在,同时提供访问该实例的全局访问方法

例如:         static A* m_instence                                    static A*getInstence()

单例模式的设计步骤:

  1. 构造函数私有
  2. 提供一个全局的静态方法(全局访问方法)
  3. 在类中定义一个静态指针,指向本类变量的静态变量指针
//Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    ~Widget();
private:
    Ui::Widget *ui;

public:
    static Widget* getInstence();//全局静态方法
private slots:
    void on_pushButton_clicked(); //测试用的槽函数

private:
    explicit Widget(QWidget *parent = 0);//构造函数私有化
private:
    static Widget* m_instence;//静态指针

};

Widget* Widget::m_instence = nullptr;

#endif // WIDGET_H
//Widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "form.h"

Widget* Widget::m_instence = nullptr;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

Widget* Widget::getInstence()
{
    //单例模式
    if(m_instence == nullptr)
    {
        m_instence = new Widget;
    }
    return m_instence;
}

void Widget::on_pushButton_clicked()
{
    Form *f = new Form;
    f->show();
    this->close();
}
//main.cpp

#include "widget.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget *w = Widget::getInstence();
    w->show();

    return a.exec();
}

测试:当在文本框输入后,跳转到跳转测试窗口,然后再返回测试窗口,输入的数据依然保持

1、懒汉式单例模式的优点

不需要使用单例时不用创建,节省内存

(懒汉式可以动态地传入参数,但是第一次传进去之后,第二次再传因为它不是空的了,所以在实际运用时可以直接入参默认值)

 

2、但是这样的单例模式在多线程编程中又会发生一些问题:(懒汉式单例模式的缺点

每次获取单例的时候要进行判断,降低了软件的性能,在多线程编程中可能会发生创建多个对象的问题(这样就不是单例了)

解决方法:线程锁,线程同步

饿汉式单例模式:

优点:对于多线程编程中比较安全

缺点:不管用还是不用都占内存,无法通过静态方法传入参数。

两者区别:

懒汉式单例模式:用的时候调用,不用的时候不调用

饿汉式单例模式:在main()函数之前初始化,或者在多线程编程的情况下使用

 

(2)简单工厂模式

又称静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式中的角色:

  1. 工厂角色:负责实现创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象。

  2. 抽象角色:所有对象的父类,共有的公共接口,负责描述所有实例

  3. 具体产品角色:具体实例对象

需求分析:

有一个水果类Fruits,创造苹果、梨子...的水果

有一个工厂类Factory,加工苹果、梨子...

class Fruits
{
public:
	virtual string getName() = 0;
};


//苹果
class Apple : public Fruits
{
public:
	string getName()
	{
		return "Apple";
	}
};
//梨
class Peer : public Fruits
{
public:
	string getName()
	{
		return "Peer";
	}
};

class Factory
{
public:
	static Fruits* Create(Fruits* fruits)
	{
		Fruits* tmp = NULL;
		if (fruits->getName() == "Apple")
		{
			tmp = new Apple(); 
		}
		else if (fruits->getName() == "Peer")
		{
			tmp = new Peer();
		}
		else
		{
			return NULL;
		}
		return tmp;
	}
};

int  main()
{
	Fruits* apple = Factory::Create(new Apple);
	cout << apple->getName() << endl;

	Fruits* peer = Factory::Create(new Peer);
	cout << peer->getName() << endl;

	return 0;
}

简单工厂模式

优点:根据具体需求,创建具体类的对象,明确区分了类与类之间的不同,有利于整个软件体系结构的优化

缺点:非“高内聚”,当具体产品类不断增多时,可扩展性不够好

 

 

(3)工厂模式

又称多态性工厂模式。核心的工厂类不再负责所有铲平的创建,而实将具体的创建工作交给子类完成,工厂类是一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,不负责具体产品类的实例化。

工厂模式主要解决接口选择问题,该模式下定义一个创建对象的接口,让其子类自己决定实例化哪个工厂类

模式中的角色:

  1. 抽象工厂角色:工厂模式的核心,任何工厂类都必须实现这个接口

  2. 具体工厂角色:抽象工厂的一个实现,负责实例化产品对象

  3. 抽象角色:所有对象的父类,共有的公共接口,负责描述所有实例所共有的接口

  4. 具体产品角色:具体实例对象

需求分析:

有一个水果类Fruits,创造苹果、梨子...的水果

有一个工厂类Factory,苹果工厂只能加工苹果,梨子加工厂只能加工梨子

//-----------水果---------------//
class Fruits
{
public:
	virtual string getName() = 0;
};

//苹果
class Apple : public Fruits
{
public:
	string getName()
	{
		return "Apple";
	}
};

//梨
class Peer : public Fruits
{
public:
	string getName()
	{
		return "Peer";
	}
};



//-----------工厂---------------//
class Factory
{
public:
	virtual Fruits* create() = 0;
};

//苹果工厂:在创造时创建苹果类对象,返回
class AppleFactory : public Factory
{
public:
	Fruits* create()
	{
		return new Apple;
	}
};

//梨工厂:在创造时创建梨类对象,返回
class PeerFactory : public Factory
{
public:
	Fruits* create()
	{
		return new Peer;
	}
};


//进入某水果加工厂,只能生产该水果
void func(Factory* factory)
{
	//水果:父类指针指向子类对象
	Fruits* fruits = factory->create();
	cout << fruits->getName() << endl;
}


int main_factory()
{
	func(new AppleFactory);
	func(new PeerFactory);

	return 0;
}

简单工厂模式 & 工厂模式:

工厂模式的核心是抽象工厂类,简单工厂模式的核心是具体类

工厂模式实现了开闭原则和可扩展性;可以应用于更复杂的需求。

工厂模式/多态性:每个具体的工厂类都有一个共有的接口/共同的抽象父类 (同一接口的不同实现)

 

 

(4)抽象工厂模式

实际上需求需要的可能不仅仅是抽象产品的实例,工厂类创建的是抽象产品的具体子类的实例。

模式中的角色:

  1. 抽象工厂角色:工厂模式的核心,任何工厂类都必须实现这个接口

  2. 具体工厂角色:抽象工厂的一个实现,负责实例化产品对象

  3. 抽象角色:所有对象的父类,共有的公共接口,负责描述所有实例所共有的接口

  4. 具体产品角色:具体实例对象

需求分析:

有一个水果类Fruits,创造苹果、梨子...的水果

有一个工厂类Factory,南方工厂加工南方苹果和南方梨子,北方加工厂加工北方苹果和北方梨子

//-----------水果---------------//
class Fruits
{
public:
	virtual string getName() = 0;
};
//北方苹果
class northApple : public Fruits
{
public:
	string getName()
	{
		return "north Apple";
	}
};
//南方苹果
class southApple : public Fruits
{
public:
	string getName()
	{
		return "south Apple";
	}
};
//北方梨
class northPeer : public Fruits
{
public:
	string getName()
	{
		return "north Peer";
	}
};
//南方梨
class southPeer : public Fruits
{
public:
	string getName()
	{
		return "south Peer";
	}
};


//-----------工厂---------------//
class Factory
{
public:
	virtual Fruits* createApple() = 0;
	virtual Fruits* createPeer() = 0;
};
//北方工厂
class northFactory : public Factory
{
public:
	Fruits* createApple()
	{
		return new northApple;
	}
	Fruits* createPeer()
	{
		return new northPeer;
	}
};
//南方工厂
class southFactory : public Factory
{
public:
	Fruits* createApple()
	{
		return new southApple;
	}
	Fruits* createPeer()
	{
		return new southPeer;
	}
};

//进入某水果加工厂,只能生产该水果
void func(Factory* factory)
{
	//水果:父类指针指向子类对象
	Fruits* apple = factory->createApple();
	Fruits* peer = factory->createPeer();
	cout << apple->getName() << endl;
	cout << peer->getName() << endl;
}

int main()
{
	//工厂:父类指针指向子类对象
	func(new northFactory);
	func(new southFactory);

	return 0;
}

 

(5)建造者模式

建造者模式是一种创建型模式,用来隐藏符合对象的创建过程,它把符合对象的创建过程加以抽象,可以通过子类继承和重载的方式动态地创建具有符合属性的对象

建造者模式的角色:

  1. Builder(抽象建造者):创建产品的各个部分,统一抽象接口
  2. ConcreteBuilder(具体建造者):具体的创建产品的某个部分
  3. Director(建造者):建造具体部分的建造者,用来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证完整创建或按照某种顺序创建对象的各个部分
  4. Product(产品):创建出来的复杂对象

需求分析:

房子类House:安装门、安装墙、安装地板

设计师类Designer:选择建造方式Builder,设计房子

建造类Builder:创造门、创造墙、创造地板、创建房子

普通建造师类CommBuilder:继承Builder

别墅建造师类VillaBuilder:继承Builder

#include 
#include 
using namespace std;

//-------------------房子--------------------//
class House
{
public:
	void setDoor(string door)
	{
		m_door = door;
	}
	void setWall(string wall)
	{
		m_wall = wall;
	}
	void setFloor(string floor)
	{
		m_floor = floor;
	}

private:
	string m_door;
	string m_wall;
	string m_floor;
};

//-------------------设计--------------------//
class Designer
{
public:
	void func_create(Builder* builder)
	{
		m_build = builder;
		m_build->createDoor();
		m_build->createFloor();
		m_build->createWall();
		m_house = m_build->getHouse();
	}

	House* getHouseDesigner()
	{
		return m_house;
	}

private:
	Builder* m_build;
	House* m_house;

};

//-------------------建造--------------------//
class Builder
{
public:
	virtual void createDoor() = 0;
	virtual void createWall() = 0;
	virtual void createFloor() = 0;
	virtual House* getHouse() = 0;

};


class CommBuilder : public Builder
{
public:
	CommBuilder()
	{
		m_house = new House;
	}
	virtual void createDoor()
	{
		m_house->setDoor("普通的门");
		cout << "创建了普通的门" << endl;
	}
	virtual void createWall()
	{

		m_house->setDoor("普通的墙");
		cout << "创建了普通的墙" << endl;
	}
	virtual void createFloor()
	{

		m_house->setDoor("普通的地板");
		cout << "创建了普通的地板" << endl;
	}

	House* getHouse()
	{
		return m_house;
	}
private:
	House* m_house;
};


class VillaBuilder : public Builder
{
public:
	VillaBuilder()
	{
		m_house = new House;
	}
	virtual void createDoor()
	{
		m_house->setDoor("别墅的门");
		cout << "创建了别墅的门" << endl;
	}
	virtual void createWall()
	{

		m_house->setDoor("别墅的墙");
		cout << "创建了别墅的墙" << endl;
	}
	virtual void createFloor()
	{

		m_house->setDoor("别墅的地板");
		cout << "创建了别墅的地板" << endl;
	}

	House* getHouse()
	{
		return m_house;
	}
private:
	House* m_house;
};

int main()
{
	Designer* d = new Designer;

	//Builder* cb = new CommBuilder;
	Builder* cb = new VillaBuilder;

	d->func_create(cb);

	House* h = cb->getHouse();

	return 0;
}

工厂模式&建造者模式:

工厂模式不考虑对象的组装过程,最终直接生成一个想要的对象

工厂模式解决的问题是工厂生产产品

建造者模式是先具体实现对象的每一个部件,最后把部件组装成一个对象

建造者模式解决的问题是工厂控制产品生成器组装各个部件的过程,然后从产品生成器中得到产品

 

 

二、结构型模式

(1)代理模式

代理模式可以为其他对象提供一种代理以控制对这个对象的访问。

代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理。

代理模式的角色:

  1. 抽象角色:代理角色和真实角色对外提供的public方法,一般为一个接口
  2. 真实角色:需要实现抽象角色接口,定义真实角色所要实现的业务逻辑,以便代理角色调用(真正的业务逻辑)
  3. 代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实的业务逻辑方法来实现抽象方法,可以附加操作,将同意的流程控制都放到代理角色中处理

需求分析:

店类Shop:抽象角色

书店类BookShop:真实角色,可以卖书,书店给了代理权给淘宝店

淘宝店类Taobao:代理角色,可以做营销(打折),然后卖书

#include 
using namespace std;

class Shop
{
public: 
	virtual void sell() = 0;
private:
};

class BookShop : public Shop
{
public:
	virtual void sell()
	{
		cout << "卖书" << endl;
	}
private:
};


class Taobao : public Shop
{
public:
	Taobao(Shop *bs)  //淘宝是书店的代理
	{
		m_bs = bs;
	}
	virtual void sell()
	{
		discount();

		cout << "让书店发货" << endl;

		m_bs->sell();
	}
	void discount()
	{
		cout << "打折" << endl;
	}

private:
	Shop *m_bs;
};

int main()
{
	Shop *pb = new BookShop;
	cout << "-------------书店卖书---------" << endl;
	pb->sell();

	Shop* pt = new Taobao(pb);
	cout << "------------淘宝店卖书---------" << endl;
	pt->sell();

	return 0;
}

【C++】设计模式_第1张图片

适合于:

为其他对象提供一种代理以控制对这个对象的访问

 

(2)装饰模式

装饰模式又叫做包装模式。通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案。给基础类挂载其他功能

装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。

代理模式的角色:

  1. 抽象构件角色:给出一个抽象接口,以回访增加附加功能的对象
  2. 具体构件角色:定义一个将要增加附加功能的类
  3. 装饰角色:拥有一个构建对象的实例,并定义一个与抽象构件接口一致的接口
  4. 具体装饰角色:负责给构件角色增加附加功能

需求分析:

游戏类Player:抽象构建角色

吃鸡玩家类chijiPlayer:具体构建角色,将要增加一些附加功能(会开车,会打枪)

CF玩家类CFPlayer:具体构建角色,将要增加一些附加功能(会跑步,会打枪)

玩家有枪类PlayerWithGun:玩家有了会开枪这个附加功能

玩家有车类PlayerWithCar:玩家有了开车这个附加功能

#include 
using namespace std;

class Player
{
public:
	virtual void play() = 0;
	virtual void show() = 0;
};

class chijiPlayer : public Player
{
public:
	virtual void play()
	{
		cout << "会拳击" << endl;
	}
	virtual void show()
	{
		cout << "吃鸡玩家" << endl;
	}
private:
};
class CFPlayer : public Player
{
public:
	virtual void play()
	{
		cout << "会跑步" << endl;
	}
	virtual void show()
	{
		cout << "穿越火线玩家" << endl;
	}
private:
};

class PlayerWithGun : public Player
{
public:
	PlayerWithGun(Player* play)
	{
		m_play = play;
	}
	virtual void play()
	{
		m_play->play();
		cout << "会打枪" << endl;
	}
	virtual void show()
	{
		m_play->show();
	}
	
private:
	Player* m_play;
};


class PlayerWithCar : public Player
{
public:
	PlayerWithCar(Player* play)
	{
		m_play = play;
	}
	virtual void play()
	{
		m_play->play();
		cout << "会开车" << endl;
	}
	virtual void show()
	{
		m_play->show();
	}

private:
	Player* m_play;
};

int main_3()
{
	cout << "--------------吃鸡--------------" << endl;
	chijiPlayer* player = new chijiPlayer();
	cout << "吃鸡 + 枪:" << endl;
	PlayerWithGun* chijiPlayerGun = new PlayerWithGun(player);
	chijiPlayerGun->play();
	chijiPlayerGun->show();

	cout << endl << "吃鸡 + 车:" << endl;
	PlayerWithCar* chijiPlayerCar = new PlayerWithCar(player);
	chijiPlayerCar->play();
	chijiPlayerCar->show();

	cout << endl << "吃鸡 + 枪 + 车:" << endl;
	PlayerWithCar* chijiPlayerCarGun = new PlayerWithCar(chijiPlayerGun);
	chijiPlayerCarGun->play();
	chijiPlayerCarGun->show();

	cout << endl << "--------------CF--------------" << endl;
	CFPlayer* CFplayer = new CFPlayer();
	cout << "CF + 枪:" << endl;
	PlayerWithGun* CFPlayerGun = new PlayerWithGun(CFplayer);
	CFPlayerGun->play();
	CFPlayerGun->show();

	cout << endl << "CF + 车:" << endl;
	PlayerWithCar* CFPlayerCar = new PlayerWithCar(CFplayer);
	CFPlayerCar->play();
	CFPlayerCar->show();

	cout << endl << "CF + 枪 + 车:" << endl;
	PlayerWithCar* CFPlayerCarGun = new PlayerWithCar(CFPlayerGun);
	CFPlayerCarGun->play();
	CFPlayerCarGun->show();
	return 0;
}

【C++】设计模式_第2张图片

适用于:

1、需要扩展一个类的功能,或给一个类增加附加功能

2、需要动态地给一个对象增加功能,这些功能也可以动态地销毁

3、需要增加一些基本功能的排列组合以产生更多的功能

 

(3)适配器模式

适配器模式可以改变已有类(或外部类)的接口形式。

适配器模式的角色:

  1. 目标接口:客户所期待的具体/抽象类,也可以是接口
  2. 需要适配的类
  3. 适配器类:通过在内部包装一个需要适配的类的对象,把源接口转换成目标接口

需求分析:

5V类dian5V:客户所期待的,5v电压,与220v不能直接兼容

220V类dian220V:需要适配的类,输出220v电压,与5v不能直接兼容

适配器类Adapter:把源接口转换成目标接口

#include 
using namespace std;

class dian5V
{
public:
	void yondian()
	{
		cout << "输出5V电压" << endl;
	}
};

class dian220V
{
public:
	void yongdian()
	{
		cout << "输入220V电压" << endl;
	}
};

class Adapter : public dian5V
{
public:
	Adapter(dian220V* dian220)
	{
		m_dian220 = dian220;
	}

	void work()
	{
		m_dian220->yongdian();
		cout << "将220V电压转换为5V" << endl;
		this->yondian();
	}

private:
	dian220V* m_dian220;
};

int main_4()
{
	dian220V* d = new dian220V;
	Adapter* a = new Adapter(d);
	a->work();

	return 0;
}

 

(4)桥接模式

桥接模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。

它的主要特点是把抽象与行为实现分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。

桥接模式的角色:

  1. 抽象构件角色:抽象类接口(接口或抽象类)维护对行为实现的引用
  2. 具体构件角色:抽象角色的真实角色类
  3. 实现角色:行为实现类接口
  4. 具体实现角色:行为实现类的具体实现子类

需求分析:

引擎类Engine:抽象类

A引擎AEngine:Engine的子类

B引擎BEngine:Engine的子类

车类Car:抽象类,要通过安装引擎来实现

宝马车BWM:Car的子类,可以安装A引擎也可以安装B引擎

奔驰车Benz:Car的子类,可以安装A引擎也可以安装B引擎

#include 
using namespace std;

class Engine
{
public:
	virtual void installEngin() = 0;
private:
};


class AEngine : public Engine
{
public:
	virtual void installEngin()
	{
		cout << "安装A引擎" << endl;
	}
private:
};

class BEngine : public Engine
{
public:
	virtual void installEngin()
	{
		cout << "安装B引擎" << endl;
	}
private:
};

class Car
{
public:
	virtual void installCar() = 0;
private:
	Engine* m_engine;
};

class BMW : public Car
{
public:
	BMW(Engine* engine)
	{
		m_engine = engine;
	}
	virtual void installCar()
	{
		m_engine->installEngin();
		cout << "安装BMW的其他部件" << endl;
	}
private:
	Engine* m_engine;
};

class Benz : public Car
{
public:
	Benz(Engine* engine)
	{
		m_engine = engine;
	}
	virtual void installCar()
	{
		m_engine->installEngin();
		cout << "安装Benz的其他部件" << endl;
	}
private:
	Engine* m_engine;
};


int main()
{
	AEngine* AE = new AEngine;
	BEngine* BE = new BEngine;

	cout << "---------------------BMW:A引擎---------------------" << endl;
	BMW* bmwA = new BMW(AE);
	bmwA->installCar();

	cout << "---------------------BMW:B引擎---------------------" << endl;
	BMW* bmwB = new BMW(BE);
	bmwB->installCar();

	cout << "---------------------Benz:A引擎---------------------" << endl;
	Benz* benzA = new Benz(AE);
	benzA->installCar();

	cout << "---------------------Benz:B引擎---------------------" << endl;
	Benz* benzB = new Benz(BE);
	benzB->installCar();


	return 0;
}

【C++】设计模式_第3张图片

 适用于:

桥接模式是将抽象部分与实现部分分离(解耦合),使它们都可以独立的变化

 

(5)外观模式

外观模式是由GoF提出的23种设计模式中的一种。

外观模式为一组具有类似功能的类群,比如类库,子系统等等,提供一个一致的简单的界面

外观模式的角色:

  1. 调用接口:调用方,定义简单的调用接口
  2. 调用者:通过调用接口调用提供某功能的内部类群
  3. 功能提供者:提供功能的类群(模块或子系统)

适用于:

子系统中统一的一套接口,去批量调用子系统的接口

例如:用于游戏初始化是批量调用系统中的接口(界面初始化、通信初始化、网络初始化...)

 

(6)享元模式

享元模式通过与其他类似对象共享数据来减小内存占用。

享元模式的角色:

  1. 抽象享元角色:所有具体享元类的父类,规定一些需要实现的公共接口
  2. 具体享元角色:抽象享元角色的具体实现类,并实现了抽象享元角色规定的方法
  3. 享元工厂角色:负责创建和管理享元角色

需求分析:

人类Person:抽象角色【年龄,姓名】

老师类Teacher:具体的角色【id,年龄,姓名】,Person的子类

工厂老师类FactoryTeacher:通过id查找老师中是否有该人,没有此人则存入信息,有此人则输出

#include 
#include 
#include 
using namespace std;

class Person
{
public:
	Person(int age, string name)
	{
		m_age = age;
		m_name = name;
	}
public:
	int m_age;
	string m_name;
};

class Teacher : public Person
{
public:
	Teacher(int id, int age, string name)
		:Person(age,name),
		m_id(id)
	{}
public:
	int m_id;
};

class FactoryTeacher
{
public:
	Teacher* getTeacher(int id)
	{
		Teacher* t = nullptr;
		map::iterator it = m_map.find(id);
		if (it == m_map.end())
		{
			int age;
			string name;

			cout << "查无此人!存入信息...." << endl;
			/*int yn;
			do {
				cout << "查无此人!是否存入信息(y/n)?";
				cin >> yn;
			} while (yn != 'y' && yn!= 'n');*/

			//if(yn == 'y')
			//{
				cout << "请输入年龄:";
				cin >> age;
				cout << "请输入姓名:";
				cin >> name;

				t = new Teacher(id, age, name); //构造对象

				m_map[id] = t; //!!!插入到map中
			//}
		}
		else
		{
			t = it->second;
		}
		return t;
	}
private:
	map m_map;
};

int main_7()
{
	FactoryTeacher* ft = new FactoryTeacher;
	int id;

	while (1)
	{
		cout << "请输入id:";
		cin >> id;
		
		Teacher *t = ft->getTeacher(id);
		cout << "id:" << t->m_id << endl << "age:" << t->m_age << endl << "name:" << t->m_name << endl;
	}

	return 0;
}

【C++】设计模式_第4张图片

使用场景:

是以共享的方式高效的支持大量的细粒度的对象。

 

三、行为型模式

(1)观察者模式

观察者模式中分为观察者和被观察者。当被观察者发生改变时,观察者会收到通知。

观察者模式:定义对象间的一对多的依赖关系,是关联对象中的一种同步通信手段,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。主要为了解决对象状态改变给其他对象通知的问题,其实现类似于观察者在被观察者中注册了一个回调函数。

观察者模式的角色:

  1. 被观察者Subject:被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。【需要维持(添加,删除,通知)一个观察者对象的队列列表。】
  2. 具体被观察者:被观察者的具体实现。包含一些基本的属性状态及其他操作。
  3. 观察者Observer:接口或抽象类。当被观察者的状态发生变化时,观察者对象将通过一个callback函数得到通知。
  4. 具体观察者:观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。

需求分析:

被观察者类Subject:添加观察者、删除观察者、通知

具体被观察者类,老师类Teacher:添加观察者、删除观察者、通知

具体被观察者类,校长类Xiaozhang:添加观察者、删除观察者、通知

观察者Observer:更新状态

具体观察者类,学生类Student:更新状态

//普通观察者模式

#include 
#include 
#include 
using namespace std;

class Observer;

class Subject
{
public:
	virtual void add(Observer *o) = 0;
	virtual void remove(Observer* o) = 0;
	virtual void notify(string msg) = 0;

protected:
	list m_list;
};

class Observer
{
public:
	virtual void update(string msg) = 0;
	virtual void subscribe(Subject* s) = 0;
	virtual void disSub(Subject* s) = 0;
protected:
	string name;
};

class Teacher : public Subject
{
public:
	Teacher()
	{
		m_list.clear();
	}
	virtual void add(Observer* o)
	{
		m_list.push_back(o);
	}
	virtual void remove(Observer* o)
	{
		m_list.remove(o);
	}
	virtual void notify(string msg)
	{
		list::iterator it = m_list.begin();
		while (it != m_list.end() )
		{
			(*it)->update(msg);
			it++;
		}
	}
private:
};

class Xiaozhang : public Subject
{
public:
	Xiaozhang()
	{
		m_list.clear();
	}
	virtual void add(Observer* o)
	{
		m_list.push_back(o);
	}
	virtual void remove(Observer* o)
	{
		m_list.remove(o);
	}
	virtual void notify(string msg)
	{
		list::iterator it = m_list.begin();
		while (it != m_list.end())
		{
			(*it)->update(msg);
			it++;
		}
	}
private:
};

class Student : public Observer
{
public:
	Student()
	{
		name = "";
	}
	Student(string name)
	{
		this->name = name;
	}
	virtual void update(string msg)
	{
		if (msg == "老师来了")
		{
			cout << name << "收起手机" << endl;
		}
		else if (msg == "老师走了")
		{
			cout << name << "掏出手机" << endl;
		}
		else if (msg == "校长来了")
		{
			cout << name << "没收手机" << endl;
		}
		else if (msg == "校长走了")
		{
			cout << name << "归还手机" << endl;
		}
	}
};

int main()
{
//创建学生
	Student* s1 = new Student("wang");
	Student* s2 = new Student("Li  ");
	Student* s3 = new Student("Xie ");
	Student* s4 = new Student("Liu ");
	Student* s5 = new Student("Zhao");

//创建老师
	Teacher* t = new Teacher;

//老师在观察者列表中添加学生
	t->add(s1);
	t->add(s2);
	t->add(s3);
	t->add(s4);
	t->add(s5);

//老师发布通知
	t->notify("老师来了");

	system("pause");

	t->notify("老师走了");

	return 0;
}

【C++】设计模式_第5张图片

典型应用

- 侦听事件驱动程序设计中的外部事件

- 侦听/监视某个对象的状态变化

- 发布者/订阅者模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者

适用于:

定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。

上升为发布者/订阅者模型:

发布者/订阅者模型的角色:

  1. 被观察者Subject:被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。【需要维持(添加,删除,通知)一个观察者对象的队列列表。】
  2. 具体被观察者:被观察者的具体实现。包含一些基本的属性状态及其他操作。
  3. 观察者Observer:接口或抽象类。当被观察者的状态发生变化时,观察者对象将通过一个callback函数得到通知。【订阅被观察值、取消订阅、接收通知】
  4. 具体观察者:观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
#include 
#include 
#include 
using namespace std;

class Observer;

class Subject
{
public:
	virtual void add(Observer *o) = 0;
	virtual void remove(Observer* o) = 0;
	virtual void notify(string msg) = 0;

protected:
	list m_list;
};

class Observer
{
public:
	virtual void update(string msg) = 0;
	
	virtual void subscribe(Subject* s) = 0;
	virtual void disSub(Subject* s) = 0;
	
protected:
	string name;
};

class Teacher : public Subject
{
public:
	Teacher()
	{
		m_list.clear();
	}
	virtual void add(Observer* o)
	{
		m_list.push_back(o);
	}
	virtual void remove(Observer* o)
	{
		m_list.remove(o);
	}
	virtual void notify(string msg)
	{
		list::iterator it = m_list.begin();
		while (it != m_list.end() )
		{
			(*it)->update(msg);
			it++;
		}
	}
private:
};

class Xiaozhang : public Subject
{
public:
	Xiaozhang()
	{
		m_list.clear();
	}
	virtual void add(Observer* o)
	{
		m_list.push_back(o);
	}
	virtual void remove(Observer* o)
	{
		m_list.remove(o);
	}
	virtual void notify(string msg)
	{
		list::iterator it = m_list.begin();
		while (it != m_list.end())
		{
			(*it)->update(msg);
			it++;
		}
	}
private:
};

class Student : public Observer
{
public:
	Student()
	{
		name = "";
	}
	Student(string name)
	{
		this->name = name;
	}
	virtual void update(string msg)
	{
		if (msg == "老师来了")
		{
			cout << name << "收起手机" << endl;
		}
		else if (msg == "老师走了")
		{
			cout << name << "掏出手机" << endl;
		}
		else if (msg == "校长来了")
		{
			cout << name << "没收手机" << endl;
		}
		else if (msg == "校长走了")
		{
			cout << name << "归还手机" << endl;
		}
	}
	
	virtual void subscribe(Subject* s)
	{
		s->add(this);
	}
	virtual void disSub(Subject* s)
	{
		s->remove(this);
	}

};

class Director : public Observer
{
public:
	virtual void update(string msg)
	{
		if (msg == "老师来了")
		{
			cout << "所有老师开会" << endl;
		}
		else if (msg == "老师走了")
		{
			cout << "所有老师散会" << endl;
		}
	}
	
	virtual void subscribe(Subject* s)
	{
		s->add(this);
	}
	virtual void disSub(Subject* s)
	{
		s->remove(this);
	}
	
}; 


int main()
{
//创建学生(观察者)
	Student* s1 = new Student("wang");
	Student* s2 = new Student("Li  ");
	Student* s3 = new Student("Xie ");
	Student* s4 = new Student("Liu ");
	Student* s5 = new Student("Zhao");

//创建主任(观察者)
	Director* derector = new Director;

//创建老师
	Teacher* t = new Teacher;

//创建校长
	Xiaozhang* xz = new Xiaozhang;
	
//被观察者订阅
	s1->subscribe(t);
	s1->subscribe(xz); //s1订阅老师和校长
	s2->subscribe(t);
	s3->subscribe(t);
	s4->subscribe(t);
	s5->subscribe(t);
	derector->subscribe(t); //主任订阅老师

//观察者发布通知
	t->notify("老师来了");
	xz->notify("校长来了");

	system("pause");

	t->notify("老师走了");
	xz->notify("校长走了");

	return 0;
}

【C++】设计模式_第6张图片

 


 

单例模式的多线程安全问题:

单例模式在多线程下是不安全的,可能会同时创建多个实例,因此为了保证单例模式在多线程下是安全的,有以下几种方式:

  1. 饿汉式:instence在类装载时就实例化,可能会产生垃圾对象
  2. 懒汉式:通过双重解锁机制实现线程安全

 

说说工厂模式的优点:

  1. 解耦合
  2. 代码复用
  3. 容易更改功能实现

 

装饰模式和单例模式,使用单例模式应该注意什么?

装饰模式:一种用于代替继承的技术,无需通过继承就可以增加子类的扩展功能。把对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀

  • 优点:装饰模式中的装饰类和被装饰类可以独立发展,不会相互耦合
  • 缺点:多层装饰比较复杂

单例模式:一种常见的软件设计模式,该类负责创建自己的对象,同时确保只有单个对象被创建,整个类提供了一种访问其唯一的对象的方法,可以直接访问,不需要实例化该类的对象

  • 优点:在内存中只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(页面缓存);避免对资源的多重占用(写文件)
  • 缺点:没有接口,不能继承,与单一职责原则冲突

 

单例模式的使用场景

  1. 要求生产唯一序列号
  2. WEB中的计数器,不用每次刷新都在数据库里加一次,用单例模式先进行缓存
  3. 创建一个对象需要消耗的资源过多,例如I/0与数据库的连接

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(C++)