设计模式 | 外观模式、享元模式

举报
mindtechnist 发表于 2023/05/11 14:35:25 2023/05/11
【摘要】 目录一、外观模式1. 什么是外观模式2. 外观模式案例二、享元模式1. 什么是享元模式2. 享元模式案例一、外观模式1. 什么是外观模式Facade Pattern,外观模式,结构型设计模式之一。外观模式为一个子系统集合提供了一个一致的简单界面,并且外观包含了对各个子系统的引用,客户端可以通过这个外观来访问各个子系统。外观模式中的角色:Facade:外观类,作为调用接口,提供所有子系统的一致...

目录

一、外观模式

1. 什么是外观模式

2. 外观模式案例

二、享元模式

1. 什么是享元模式

2. 享元模式案例


一、外观模式

1. 什么是外观模式

Facade Pattern,外观模式,结构型设计模式之一。外观模式为一个子系统集合提供了一个一致的简单界面,并且外观包含了对各个子系统的引用,客户端可以通过这个外观来访问各个子系统。

外观模式中的角色:

  • Facade:外观类,作为调用接口,提供所有子系统的一致访问界面;
  • Clients:通过外观角色来访问各个子系统;
  • Subsystem:子系统,实现子系统的功能;


2. 外观模式案例

首先创建子系统集合,假设为电脑系统,定义显示屏子系统、主机子系统、键盘子系统

class Screen //子系统1
{
public:
	void get_attr()
	{
		cout << "显示屏子系统" << endl;
	}
};

class Host //子系统2
{
public:
	void get_attr()
	{
		cout << "主机子系统" << endl;
	}
};

class Keyboard //子系统3
{
public:
	void get_attr()
	{
		cout << "键盘子系统" << endl;
	}
};

 如果客户不适应外观类,而是直接访问这个子系统,那么操作将会比较繁琐

void Func1()
{
	Screen* mScreen;
	Host* mHost;
	Keyboard* mKeyboard;

	mScreen = new Screen;
	mHost = new Host;
	mKeyboard = new Keyboard;

	mScreen->get_attr();
	mHost->get_attr();
	mKeyboard->get_attr();
}

要创建每个子系统对象,并逐个调用其方法来访问子系统。

创建一个外观类,它包含对所有子系统的引用

class Facade
{
private:
	Screen* mScreen;
	Host* mHost;
	Keyboard* mKeyboard;
public:
	Facade()
	{
		mScreen = new Screen;
		mHost = new Host;
		mKeyboard = new Keyboard;
	}
	~Facade()
	{
		if (mScreen != NULL)
		{
			delete mScreen;
		}
		if (mHost != NULL)
		{
			delete mHost;
		}
		if (mKeyboard != NULL)
		{
			delete mKeyboard;
		}
	}
	void get_attr()
	{
		this->mScreen->get_attr();
		this->mHost->get_attr();
		this->mKeyboard->get_attr();
	}
};

通过外观来访问所有子系统

void Func2()
{
	Facade* f = new Facade;
	f->get_attr();
	delete f;
}

二、享元模式

1. 什么是享元模式

Flyweight Pattern,享元模式,结构型设计模式。

在面向对象系统的设计和实现中,创建对象是最常见的操作,这里就会有一个问题:如果一个应用程序使用了太多对象,就会造成很大的存储开销。特别是对于大量轻量级(细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为每一个字母创建一个对象的时候可能会因为大量的对象而造成存储开销的浪费,例如一个字母a在文档中出现了10000次,而实际上我们可以让这10000个a共享一个对象,这种情况下,我们可以将对象状态分为内部状态和外部状态。在享元模式中可以共享(不会变化)的状态称为内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为外部状态(Extrinsic State),其中外部状态和内部状态是相互独立的,外部状态的变化不会引起内部状态的变化。内部状态直接存储在对象中,而外部状态(字母a的大小、字体)可以在适当时机作为参数传递给对象。享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。

享元模式的角色:

  • Flyweight:抽象享元角色,定义了所有具体享元类的接口,通过这个接口可以传入外部状态并作用于外部状态;
  •  FlyweightFactory:享元工厂,创建并管理享元对象;
  • ConcreteFlyweight:可共享的内部状态;
  • UnsharedConcreteFlyweight:可以不共享的享元子类;

2. 享元模式案例

假设一个字符串和一个标志作为一对,可以通过标志来确定字符串,比如只要传入标志1就得到字符串hello,也就是说,通过flag可以确定一个字符串。

 

class MyStr
{
protected:
	string str;
public:
	MyStr(string str)
	{
		this->str = str;
	}
	virtual void get_str() = 0;
};

class Hello : public MyStr
{
private:
	int id;
public:
	Hello(string str, int id) : MyStr(str)
	{
		this->id = id;
	}
	virtual void get_str()
	{
		cout << "id: " << id << "  对应的str:  " << str << endl;
	}
};

创建一个工厂

class Factory
{
private:
	map<int, Hello*> m;
public:
	~Factory()
	{
		while (!m.empty())
		{
			Hello* tmp = NULL;
			map<int, Hello*>::iterator it = m.begin();
			tmp = it->second;
			m.erase(it);
			delete tmp;
		}
	}
	Hello* get_str(int id)
	{
		Hello* mtemp;
		map<int, Hello*>::iterator it;
		it = m.find(id);
		if (it == m.end())
		{
			string temp;
			cout << "该字符串未找到,请输入字符串:";
			cin >> temp;
			mtemp = new Hello(temp, id);
			m.insert(make_pair(id, mtemp));
			return mtemp;
		}
		else
		{
			return it->second;
		}
	}
};

客户端通过工厂获取享元对象,并传入一个标志

int main()
{
	Hello* h1 = NULL, * h2 = NULL;
	Factory* f = NULL;

	f = new Factory;

	h1 = f->get_str(1);
	h1->get_str();

	h2 = f->get_str(1);
	h2->get_str();

	delete h2;
	delete h1;
	delete f;

	system("pause");
	return 0;
}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。