工厂模式作为创建型设计模式,我们可以简单理解为,它就是一个创造类对象的工厂,我们需要创建某些产品时与之该工厂对接,从而达到低耦合,下面我们一步一步的去感受工厂模式在特定的时候所发挥的好处。
简单工厂模式
<?php
/**
* 小米空调遥控器控制
* Class XiaoMiAcControl
*/
class XiaoMiAcControl
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
class A{
public function __construct()
{
$xiaomi_obj = new XiaoMiAcControl();
$xiaomi_obj->open();
}
}
class B{
public function __construct()
{
$xiaomi_obj = new XiaoMiAcControl();
$xiaomi_obj->close();
}
}
class C{
public function __construct()
{
$xiaomi_obj = new XiaoMiAcControl();
$xiaomi_obj->open();
}
}
...
我定义了一个小米空调遥控器控制类XiaoMiAcControl,
当N个地方去new XiaoMiAcControl(),这样看似没有什么问题,代码执行也很正常
但是一旦当XiaoMiAcControl类需要传递参数或修改类文件名时(例如小米品牌改成大米了),就会发现事情的严重性,
我们知道大部分一个类会单独放在一个文件中,
那我们可能需要改很多很多文件的new XiaoMiAcControl()在其加上参数或修改new的对象名称,耦合度非常高,
所以我们在这种情况下延伸到简单工厂模式就可以很好的解决这个问题。
/**
* 小米空调
* Class XiaoMiAcControl
*/
class XiaoMiAcControl
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
class SimpleFactory
{
public function createXiaoMiAcControl()
{
return new XiaoMiAcControl();
}
}
class A{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())->createXiaoMiAcControl();
}
}
class B{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())->createXiaoMiAcControl();
}
}
class C{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())->createXiaoMiAcControl();
}
}
当我们加入简单工厂类SimpleFactory时,就可以很好的解决以上的问题,
当需要传递参数或修改类文件名时,只需要在SimpleFactory这一个文件中修改即可,大大的降低了耦合。
优化:像空调的基本控制功能我们可以设置为一个接口,形成接口规范
interface acFun
{
public function open();
public function close();
}
/**
* 小米空调
* Class XiaoMiAcControl
*/
class XiaoMiAcControl implements acFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
class SimpleFactory
{
public static function createXiaoMiAcControl()
{
return new XiaoMiAcControl();
}
}
class A
{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())::createXiaoMiAcControl();
}
}
class B
{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())::createXiaoMiAcControl();
}
}
class C
{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())::createXiaoMiAcControl();
}
}
工厂方法模式
简单工厂定义了一个工厂类去创建对象,但是当有多个品牌去请求创建时,我们可以看到工厂类耦合很多个品牌
interface AcFun
{
public function open();
public function close();
}
/**
* 小米空调
* Class XiaoMiAcControl
*/
class XiaoMiAcControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
/**
* 格力
* Class GreeAcFunControl
*/
class GreeAcFunControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
class SimpleFactory
{
//简单工厂在实现多个品牌类生产对象时 会看到工厂类会耦合很多品牌创建类,
//工厂方法模式就是为了解决简单工厂的这个问题,可以做到工厂类的解耦和封闭开放原则
public static function createXiaoMiAcControl()
{
return new XiaoMiAcControl();
}
public static function createGreeAcControl()
{
return new GreeAcFunControl();
}
}
class A
{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())::createXiaoMiAcControl();
}
}
class B
{
public function __construct()
{
$gree_obj = (new SimpleFactory())::createGreeAcControl();
}
}
class C
{
public function __construct()
{
$xiaomi_obj = (new SimpleFactory())::createXiaoMiAcControl();
}
}
对封闭开放原则不了解的小伙伴请点击了解~封闭开放原则
优化:下面对简单工厂创建多个产品进行解藕优化
interface AcFun
{
public function open();
public function close();
}
/**
* 小米空调
* Class XiaoMiAcControl
*/
class XiaoMiAcControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
/**
* 格力
* Class GreeAcFunControl
*/
class GreeAcFunControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
/**
* 加一个创建空调控制的接口,创建对象由对应的子类工厂去实现,达到封闭开放的原则
*/
interface AcControlFactory
{
public function createAcControl();
}
class FactoryXiaomiAc implements AcControlFactory
{
public function createAcControl()
{
return new XiaoMiAcControl();
}
}
class FactoryGreeAc implements AcControlFactory
{
public function createAcControl()
{
return new GreeAcFunControl();
}
}
class A
{
public function __construct()
{
$xiaomi_obj = (new FactoryXiaomiAc())->createAcControl();
}
}
class B
{
public function __construct()
{
$gree_obj = (new FactoryGreeAc())->createAcControl();
}
}
class C
{
public function __construct()
{
$xiaomi_obj = (new FactoryXiaomiAc())->createAcControl();
}
}
抽象工厂模式
抽象工厂模式和工厂模式一样,创建对象时都是在子类去实现并且返回一个对象。
只是抽象工厂返回的并不是一个对象,而是多个对象。
例如:现在每个品牌工厂只返回了一种控制空调的方法,但是如果现在需要加一个手机控制空调的方法呢? 在不用到抽象工厂模式下是这样的
/**
* 遥控器控制接口
* Interface AcFun
*/
interface AcFun
{
public function open();
public function close();
public function phoneOpen();//手机开启空调
public function phoneClose();//手机关闭空调
}
/**
* 小米空调
* Class XiaoMiAcControl
*/
class XiaoMiAcControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
public function phoneOpen()
{
echo '手机打开空调';
}
public function phoneClose()
{
echo '遥控器关闭空调';
}
}
/**
* 格力
* Class GreeAcControl
*/
class GreeAcControl implements acFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
public function phoneOpen()
{
echo '手机打开空调';
}
public function phoneClose()
{
echo '遥控器关闭空调';
}
}
interface AcControlFactory
{
public function createAc();
}
class FactoryXiaomiAc implements AcControlFactory
{
public function createAc()
{
return new XiaoMiAcControl();
}
}
class FactoryGreeAc implements AcControlFactory
{
public function createAc()
{
return new GreeAcControl();
}
}
class A
{
public function __construct()
{
$xiaomi_obj = (new FactoryXiaomiAc())->createAc();
$xiaomi_obj->open();
$xiaomi_obj->phoneOpen();
}
}
class B
{
public function __construct()
{
$gree_obj = (new FactoryGreeAc())->createAc();
$gree_obj->open();
$gree_obj->phoneOpen();
}
}
class C
{
public function __construct()
{
$xiaomi_obj = (new FactoryXiaomiAc())->createAc();
$xiaomi_obj->open();
$xiaomi_obj->phoneOpen();
}
}
你们发现其中的问题所在了吗,如果以后我们需要用电脑控制空调、ai控制空调、机器人控制空调,那我们需要在acFun的接口里面一直添加,是不是又是一种增加了高耦合度的动作,所以我们可以把各种控制空调的发送端再次进行抽象、解藕。
/**
* 遥控器控制接口
* Interface acFun
*/
interface AcFun
{
public function open();
public function close();
}
/**
* 手机控制接口
* Interface PhoneAcFun
*/
interface PhoneAcFun{
public function open();
public function close();
}
/**
* 小米空调遥控器控制
* Class XiaoMiAc
*/
class XiaoMiAcControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
/**
* 小米空调手机控制
* Class XiaoMiPhoneAcFun
*/
Class XiaoMiPhoneAcControl implements PhoneAcFun{
public function open()
{
echo '手机打开空调';
}
public function close()
{
echo '手机关闭空调';
}
}
/**
* 格力空调遥控器控制
* Class Gree
*/
class GreeAcFunControl implements AcFun
{
public function open()
{
echo '遥控器打开空调';
}
public function close()
{
echo '遥控器关闭空调';
}
}
/**
* 格力空调手机控制
* Class Gree
*/
class GreePhoneAcControl implements PhoneAcFun
{
public function open()
{
echo '手机打开空调';
}
public function close()
{
echo '手机关闭空调';
}
}
interface AcControlFactory
{
public function createAc();
public function createPhoneAc();
}
class FactoryXiaomiAc implements AcControlFactory
{
public function createAc()
{
return new XiaoMiAcControl();
}
public function createPhoneAc()
{
return new XiaoMiPhoneAcControl();
}
}
//主要是这里 返回多个对象
class FactoryGreeAc implements AcControlFactory
{
public function createAc()
{
return new GreeAcFunControl();
}
public function createPhoneAc()
{
return new GreePhoneAcControl();
}
}
class A
{
public function __construct()
{
$factory_obj = new FactoryXiaomiAc();
$ac_control = $factory_obj->createPhoneAc();
$phone_ac_control = $factory_obj->createPhoneAc();
$ac_control->open();
$phone_ac_control->close();
}
}
class B
{
public function __construct()
{
$factory_obj = new FactoryGreeAc();
$ac_control = $factory_obj->createPhoneAc();
$phone_ac_control = $factory_obj->createPhoneAc();
$ac_control->open();
$phone_ac_control->close();
}
}
class C
{
public function __construct()
{
$factory_obj = new FactoryXiaomiAc();
$ac_control = $factory_obj->createPhoneAc();
$phone_ac_control = $factory_obj->createPhoneAc();
$ac_control->open();
$phone_ac_control->close();
}
}
这样子应该是看的比较清楚了,
我写了两个控制空调的方法,遥控器控制和手机控制
当你创建对象的时候,可以返回控制空调所有相关的控制媒介,需要的话就调用,不需要的话就不用写
工厂抽象模式的中心其实还是工厂方法模式。
希望这篇文章可以帮到大家,如果有问题可以私信~
网友评论