深入了解23种设计模式——工厂方法

我们假设这样一种情况,当某个工厂一直用卡车进行运输,突然增加一个需求,需要增加轮船运输,那么怎么用代码实现?

众所周知,c++是面向对象的语言,我们只要抽象出一个类,使它可以实现”轮船运输“的需求即可解决。

但是如果面对工程量巨大的业务,增加这样一种需求是极为困难的。

这个时候就需要一种能够使其过程尽可能简化的东西出来。我们把它叫做组件

怎么正确认识组件呢?

你可以把它想象成一个螺丝钉,螺丝钉可以用于生活中的诸多方面。小到针针线线,大到航空航天,都需要用到螺丝钉。它的功能单一,但可以用于方方面面。

之后还需要知道一个概念:接口

每个组件根据接口连接起来,可以极大的简化开发过程。

所以说,组件化和接口化是未来企业代码发展的趋势。

一、工厂方法

说了这么多,我们今天讲一个最简单的设计模式——工厂方法。

工厂方法实现具体如下:

工厂方法的结构

工厂模式包含以下几个主要角色:

  • 抽象产品(Abstract Product):定义了产品的共同接口或抽象类。它可以是具体产品类的父类或接口,规定了产品对象的共同方法。
  • 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
  • 抽象工厂(Abstract Factory):声明了创建产品的抽象方法,可以是接口或抽象类。它可以有多个方法用于创建不同类型的产品。
  • 具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象。

应用实例

  1. 汽车制造:你需要一辆汽车,只需从工厂提货,而不需要关心汽车的制造过程及其内部实现。
  2. Hibernate:更换数据库时,只需更改方言(Dialect)和数据库驱动(Driver),即可实现对不同数据库的切换。

使用场景

  1. 日志记录:日志可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志的位置。
  2. 数据库访问:当用户不知道最终系统使用哪种数据库,或者数据库可能变化时。
  3. 连接服务器的框架设计:需要支持 "POP3"、"IMAP"、"HTTP" 三种协议,可以将这三种协议作为产品类,共同实现一个接口。

让我们再回到最初:当某个工厂一直用卡车进行运输,突然增加一个需求,需要增加轮船运输,我们该怎么解决?

我们看下面代码的UML类图:

由UML类图看出:此处有Truck和Ship两种方式,我们用多态实现功能多样化。这样的话,如果需要再增加一种需求,我们只需要新增两个类,分别实现继承自Logistics和Transport,即可实现该需求,大大简化了流程。

具体代码如下:

#include <iostream>
//产品的接口
class Transport
{
public:
	virtual ~Transport() {};
    virtual void deliver() const = 0;
};
//产品A
class Truck :public Transport{
public:
	void deliver()const override
	{
		std::cout << "卡车运输货物中" << std::endl;
	}
};
//产品B
class Ship:public Transport {
public:
	void deliver()const override
	{
		std::cout << "轮船运输货物中" << std::endl;
	}
};
//创造者
class Logistics
{
public:
	virtual ~Logistics() {};
	//工厂方法(核心)
	virtual Transport* factoryMethod() const = 0;
	//
	void doSomething()const
	{
		Transport* transport = factoryMethod();
		transport->deliver();
		delete transport;
	}
};
//具体创造者A
class TruckLogistics :public Logistics
{
public:
	virtual ~TruckLogistics() {};
	virtual Transport* factoryMethod() const override
	{
		return new Truck();
	}
};
//具体创造者B
class ShipLogistics :public Logistics
{
public:
	virtual ~ShipLogistics() {};
	virtual Transport* factoryMethod() const override
	{
		return new Ship();
	}
};

int main()
{
	Logistics* trucklogistics = new TruckLogistics();
	trucklogistics->doSomething();
	Logistics* shiplogistics = new ShipLogistics();
    shiplogistics->doSomething();
	shiplogistics->doSomething();
	delete shiplogistics;
    delete trucklogistics;
	return 0;
}

 二、工厂方法的优缺点

优点

  1. 调用者只需要知道对象的名称即可创建对象。
  2. 扩展性高,如果需要增加新产品,只需扩展一个工厂类即可。
  3. 屏蔽了产品的具体实现,调用者只关心产品的接口。

缺点

每次增加一个产品时,都需要增加一个具体类和对应的工厂,使系统中类的数量成倍增加,增加了系统的复杂度和具体类的依赖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值