PHP设计模式之工厂模式

工厂模式的定义

Define an interface for creating an object, but let subclasses decide witch class to instantiate. Factory Method lets a class defer instantiation to subclasses.
定义一个实例化对象的接口,让其子类决定要实例化哪一个具体的类。工厂方法使类的实例化延迟到其子类。

优点

创建对象从来都不是一件十分轻松的事情,尽管我们随时都可以通过new关键字来创建一个对象。正因为如此,何时何地,由谁去创建对象才显得尤为重要。
在一个复杂的系统里面,创建对象本身就不是那么轻松(比如创建对象之前还需要创建其他一系列的相关对象),而直接通过new 关键字去完成这样的操作,先不说设计,就是本身这样去写代码都变得不合实际。就别说封装性和拥抱变化了。(想想看,在重复的初始化条件和到处都遍布着new关键字的代码中,让你去寻找并一一修改某些因为需求变更而需要改变的代码,估计你会立马疯掉或者打包走人。)
如此,工厂模式的优点也就凸显出来了

  1. 良好的封装性,代码结构清晰。
    例如一个调用者需要一个产品对象,他只需要知道产品的类名称即可。至于创建产品本身有多么困难,对于他来说毫不在意。因为工厂(创建产品的类)会帮他搞定。
  2. 优秀的扩展能力。
    在增加产品类的情况下,只需要适当修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”。
  3. 屏蔽产品类。
    对于调用者而言,根本不用关心产品类本身是如何实现的,只要产品的接口不变,就是稳定的。

使用场景

new 一个对象的替代品,任何需要生成对象的地方都可以使用,前提是,是不是一定要增加一个工厂类来完成实例化,从而增加代码的复杂度。
又比如发送邮件,我们可能会用到不同的协议去连接邮件服务器,POP3, HTTP,IMAP,SMTP等,我们可以把不同的协议当做不同的产品,当切换协议时,我们就切换不同的工厂去实例化对应的产品

UML类图

严格来说,下面是一个多工厂类的类图。如果去掉CreatorA 和 ProductA 基本就是一个最简单的通用类图了。相对于区分工厂模式和其扩展模式而言,搞清楚何时去使用它们要重要得多。因为它们都是工厂模式,只是便于我们理解,以及如何灵活的改变这个模式以适应环境而加以区分罢了。
php工厂模式

扩展

工厂模式的扩展有很多,且可以与其他模式结合使用,模式并不在于模式本身,而在于使用者的灵活变通。

缩小为简单工厂模式

去掉抽象的工厂类即可,Creator::create() 方法会知道何时去创建相对应的产品。写作如下:

<?php
class Creator
{
	const TAG_A = 1;
	const TAG_B = 2;
	
	//这里是模拟的情况
	public static function create ($tag) {
		switch ($tag) {
			case (self::TAG_B):
				return new ProductB();
				break;
			default:
				return new ProductA();
				break;
		}
	}
}

php简单工厂模式
此模式也叫静态工厂模式。结构、代码,相对来说都要简单很多。当然缺点也是显而易见的,工厂类的扩展是比较困难的。随着产品的增加,工厂类 Creator 的 create 方法将变得不堪重负。

升级为多个工厂类

如上上UML类图所示。这个模式顾名思义,就是有多个创建产品的工厂类。一般是一一对应的。比如,工厂类 CreatorA 就是专门用来创建产品 ProductA 的,以此类推。这里可以思考一下为何要分成多个工厂,如果创建对象的方式都是一样的。干嘛还要分开呢?必然创建对象的方式可能都不一样,或者不都一样。
如果创建产品A 需要的参数和创建产品B 需要的参数不一样呢,甚至还有更多的产品。

扩展为抽象工厂模式

定义

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
为创建一组相关或相互依赖的对象提供的一个接口,而且无需指定他们的具体类。

类图

下面是抽象工厂模式的类图
php抽象工程模式
这样抽象工厂的具体实现类就能创建一组产品,这组产品可以是相关或者相互依赖的,也可以是没有任何关系的。因为抽象产品类ProductA 和 ProductB 可能继承于同一高层产品的抽象类,也可以是独立毫无关联的。

使用场景

假设要开发一款跨操作系统的软件,对于软件而言,即使是不同的操作系统,功能和UI应该都是十分相似的,不同的是在不同的操作系统上调用不同的工厂方法,由不同的产品类去处理与系统的交互信息。

注意点

值得注意的是,在抽象工厂模式中,如果有N个产品家族,那就有N个方法去创建他们,如果有L个产品等级,也就有L个工厂类。(类图中,ProductA 和 ProductB 可以理解为产品家族,而它们下面的产品类可以理解为产品等级)
此模式的特点是,横向(产品等级)扩展容易,纵向(产品家族)扩展难。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值