Laravel 中的简单工厂和抽象工厂

1,619 阅读3分钟
原文链接: mp.weixin.qq.com

设计模式之工厂模式分为两种:简单工厂和抽象工厂模式,工厂模式属于“创建”型的设计模式,顾名思义用来实例化对象,调用者不需要关心对象的具体位置和实现,工厂模式隐藏了背后的细节,从而实现了解耦的目的。

在大多数面向对象的语言中,实例化对象基本上都是 new ClassA() 这样创建实例,有两个原因不建议这么做:1.上层使用者没有和对象的创建过程隔离,导致代码耦合度高 2.创建对象实例的过程可能比较复杂,比如一些前置的过程。所以把这个创建过程交给工厂方法,调用者不用关心实例是怎么创建的。

工厂是生产产品的,这里产品指的就是具体的实例。简单工厂和抽象工厂设计模式都是为了解决类的实例化,避免 new XX()带来的代码耦合。

简单工厂模式

简单工厂模式可以通过一个工厂方法,或者说一个函数,比如传入一个参数,工厂方法根据这个参数返回具体类的实例。它相当于多了一层封装,你只要关心需要什么实例,它就返回什么实例,而不用直接实例化,实例化的过程交给了工厂方法。

Laravel 中一个数据库连接的工厂类:

  1. vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php

  1. protected function createConnection($driver, $connection, $database, $prefix = '', array $config = [])

  2. {

  3.    if ($this->container->bound($key = "db.connection.{$driver}")) {

  4.        return $this->container->make($key, [$connection, $database, $prefix, $config]);

  5.    }

  6.    switch ($driver) {

  7.        case 'mysql':

  8.            return new MySqlConnection($connection, $database, $prefix, $config);

  9.        case 'pgsql':

  10.            return new PostgresConnection($connection, $database, $prefix, $config);

  11.        case 'sqlite':

  12.            return new SQLiteConnection($connection, $database, $prefix, $config);

  13.        case 'sqlsrv':

  14.            return new SqlServerConnection($connection, $database, $prefix, $config);

  15.    }

  16.    throw new InvalidArgumentException("Unsupported driver [$driver]");

  17. }

这里根据配置文件数据库驱动的配置,返回对应数据库的连接对象的实例。

简单工厂模式符合 单一职责原则 ,也就是每个类只做一件事情,但不符合 开放封闭原则 ,每次增加和减少所需实例都需要改动代码,不能做到很好的扩展。

抽象工厂模式

抽象工厂模式在简单工厂模式基础上,多了一层抽象工厂接口,它的思想是,假如有多个工厂生产同样的产品,他们有同样的行为,那么把这些产品的创建行为抽象出来,每个工厂实现这个抽象接口。

适用场景

有多个工厂,生产同一类型的产品,如下所示:

工厂1

产品1 产品2 产品3 工厂2

产品1 产品2 产品3 以 Mac 系统和 Windows 系统为例,都有创建 button 和创建 border 功能,这两个工厂都可以生产 button 和 border,那么把创建这两个产品的方法抽象出来,这个抽象出来的方法叫做抽象工厂类,两个工厂都要实现这个抽象类。

PHP 抽象工厂代码示例:

  1. abstract class AbstractFactory {

  2. abstract public function CreateButton();

  3. abstract public function CreateBorder();

  4. }

  5. class MacFactory extends AbstractFactory{

  6. public function CreateButton()

  7. {

  8. return new MacButton();

  9. }

  10. public function CreateBorder()

  11. {

  12. return new MacBorder();

  13. }

  14. }

  15. class WinFactory extends AbstractFactory{

  16. public function CreateButton()

  17. {

  18. return new WinButton();

  19. }

  20. public function CreateBorder()

  21. {

  22. return new WinBorder();

  23. }

  24. }

  25. class Button{}

  26. class Border{}

  27. class MacButton extends Button{

  28. function __construct()

  29. {

  30. echo 'MacButton is created' . "\n";

  31. }

  32. }

  33. class MacBorder extends Border{

  34. function __construct()

  35. {

  36. echo 'MacBorder is created' . "\n";

  37. }

  38. }

  39. class WinButton extends Button{

  40. function __construct()

  41. {

  42. echo 'WinButton is created' . "\n";

  43. }

  44. }

  45. class WinBorder extends Border{

  46. function __construct()

  47. {

  48. echo 'WinBorder is created' . "\n";

  49. }

  50. }

  51. ?>

从工厂取出实例:

  1. <?

  2. $type = 'Mac'; //value by user.

  3. if(!in_array($type, array('Win','Mac')))

  4.    die('Type Error');

  5. $factoryClass = $type.'Factory';

  6. $factory=new $factoryClass;

  7. $factory->CreateButton();

  8. $factory->CreateBorder();

  9. ?>