创建型模式


这么大岁数了才开始研究设计模式,而且一直没有理解。现在明白了,虽然我能看懂代码,但是感觉并没有领会其中的意思,主要的思想就是目前的需求能不能用这个模式,如果用,要怎么写。

1. 工厂模式

1.1 内容

既然叫做“工厂”,思路要在工厂是如何生产产品的。整体的思路是这样的,每种工厂和每种产品是绑定的,即每种工厂只能生产一种产品,相加产品,必须加工厂,但是生产的产品都是符合国家标准的。而工厂也有统一要求,每个实际的工厂也都要符合国家标准。通过抽象的工厂和抽象的产品的指针,通过多态调用子类的函数。

因此工厂模式一共分为四个东西

![][pic-factory]

  1. 抽象产品类:这个类是纯虚的,提供各种接口,通俗的说就是产品的规范
  2. 具体产品类:这个类是实际的产品,需要实现父类(即抽象产品类)的方法
  3. 抽象工厂类:这个类是纯虚的,提供各种接口,通俗的说就是工厂的规范
  4. 具体工厂类:这个类是实际的工厂,需要实现父类(即抽象工厂类)的方法

实际调用的时候工厂类负责生成各种产品,使用产品的过程是放在主函数里啊,还是放在工厂里啊都行。

书上管工厂叫创建者。下面代码和书上的差别不大,只是我把使用产品的代码写在了main里面。此外对没有支持rule of five,也没有使用智能指针,多线程也没有考虑,代码不够标准,只为了显示工厂模式的特点。

#include<stdc++.h>
using namespace std;
class Product
{
	public:
		virtual void SetName(string name) = 0;
		virtual void SetColor(string color) = 0;
		virtual string GetName() = 0;
		virtual string GetColor() = 0;
		virtual ~Product()=default;
};

class ProductNokia:public Product
{
	public:
		void SetName(string name)
		{
			name_ = name;
		}

		void SetColor(string color)
		{
			color_ = color;
		}
		string GetName()
		{
			return name_;
		}

		string GetColor()
		{
			return color_;
		}
		virtual ~ProductNokia() = default;
	private:
		string name_;
		string color_;
};


class Creator
{
	public:
		virtual Product* CreateProduct() = 0;
		virtual ~Creator() = default;
};

class CreatorNokia:public Creator
{
	public:
		Product* CreateProduct()
		{
			return new ProductNokia();
		}
		virtual ~CreatorNokia() = default;
};


int main()
{
	Creator* p_creator = new CreatorNokia();///<搞一个工厂
	Product* p_nokia = p_creator->CreateProduct();///<用工厂创建一个产品
	p_nokia->SetName("nokia");
	p_nokia->SetColor("blue");
	cout<<"name="<<p_nokia->GetName()<<",color="<<p_nokia->GetColor()<<endl;
	delete(p_creator);
	delete(p_nokia);
	return 0;
}
1.2 实现方法

声明一个产品的抽象,不管多少个产品都实现这个抽象产品类。每种产品一个创建者,想要什么产品就用创建者去创建。使用产品的时候调用抽象产品就行了(意思就是实际产品和抽象工厂根本不用对外提供)。注意:这个抽象工厂根本就不是抽象工厂类,只是不想写switch-case而已。

或者工厂不想抽象一下可以用switch-case替代。就是对外提供的是一个工厂类和一个抽象产品类,想造什么,就通过参数把要创建的产品名称传进去,工厂内部会生成一个对应的指针,再用抽象产品的调用方式“使用”这个产品。

1.3 适用场景(没看懂,抄的)
  1. 当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法

2.如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法

3.如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。

1.4 优缺点(觉得没用,抄的)

优点:

  1. 你可以避免创建者和具体产品之间的紧密耦合。
  2. 单一职责原则。你可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。
  3. 开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。

缺点:

应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。 最好的情况是将该模式引入创建者类的现有层次结构中。

2. 抽象工厂

2.1 内容

其实抽象工厂和普通工厂一样,只不过普通工厂只能生产一种产品。工厂的例子中是手机,不管是诺基亚还是小米还是谷歌手机,都是手机,但如果我此时还要生产电视呢?搞一个公共的虚基类。只不过电视、手机和这个基类的关系并不是继承,而是组合。

听起来有点难懂哈,因为电视和手机要抽出一个公共的基类,但是要避免使用继承而多使用组合,所以就搞一个基类,这个基类有两个成员变量:电视和手机。这样的话哪怕以后有几十种产品都不用去找它们的共同点了,组合就OK了。

不过既然抽象工厂可以生产多种产品,那么所有的实际工厂类都要实现这些方法。以下面的为例,抽象工厂可以生成电视和手机,那么这两个工厂就必然是苹果工厂和一加工厂,而它们的任务还是制造产品,每个工厂制造的产品返回的指针还是用抽象产品类的来接,以便实现多态。

抽象工厂的组成部分和工厂差不多,图中多了的那个客户端不是很有所谓,反正就是多态指针的使用。

下面代码还是只表示关系,未测试。

#include<stdc++.h>
using namespace std;

class Mobile///<抽象产品1-手机
{
	public:
		virtual string GetName()=0;
		virtual ~Mobile()=default;
};

class OnePlusMobile : public Mobile
{
	public:
		string GetName()
		{return "OnePlusMobile";}
};

class AppleMobile : public Mobile
{
	public:
		string GetName()
		{return "AppleMobile";}
};


class TV///<抽象产品2-电视
{
	public:
		virtual string GetName()=0;
		virtual ~TV()=default;
};

class OnePlusTV : public TV
{
	public:
		string GetName()
		{return "OnePlusTV";}
};

class AppleTV : public TV
{
	public:
		string GetName()
		{return "AppleTV";}
};

class AbstractFactory
{
	public:
	
		virtual Mobile* CreateMobile()=0;///<组合关系
		virtual TV* CreateTV()=0;
		virtual ~AbstractFactory() = default;
};

class OnePlusFactory : public AbstractFactory///<因为是组合的,所以所有工厂都要把两个产品的制造实现出来
{
	public:
		Mobile * CreateMobile() override
		{return new OnePlusMobile;}
		TV * CreateTV() override
		{return new OnePlusTV;}
};

class AppleFactory : public AbstractFactory
{
	public:
		Mobile * CreateMobile() override
		{return new AppleMobile;}
		TV * CreateTV() override
		{return new AppleTV;}
};


int main()
{
	OnePlusFactory* p_one = new OnePlusFactory;
	AppleFactory* p_apple = new AppleFactory;

	auto apple_mobile = p_apple->CreateMobile();
	std::cout<<apple_mobile->GetName()<<std::endl;;


	auto one_TV = p_one->CreateTV();
	std::cout<<one_TV->GetName()<<std::endl;

	return 0;
}
2.2 适用场景(没看懂)
  1. 如果代码需要与多个不同系列的相关产品交互,但是由于无法提前获取相关信息,或者出于对未来扩展性的考虑,你不希望代码基于产品的具体类进行构建,在这种情况下,你可以使用抽象工厂。

  2. 如果你有一个基于一组抽象方法的类,且其主要功能因此变得不明确,那么在这种情况下可以考虑使用抽象工厂模式。

2.3 优缺点(还是感觉没用)

优点:

  1. 你可以确保同一工厂生成的产品相互匹配。
  2. 你可以避免客户端和具体产品代码的耦合。
  3. 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
  4. 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。

缺点:

由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。

3.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tux~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值