简单介绍下几种常见的创建型设计模式:

  • Singleton 单例模式
  • Factory 工厂模式
  • Prototype 原型模式
  • Builder 建造者模式

Singleton 单例模式

单例模式也是最常见的模式之一,它确保一个类只有一个实例,并提供一个全局的访问点。

主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误。比如 Redis、MySQL 连接、CURL 句柄等。

RedisUtil.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class RedisUtil
{
protected $redis = null;

protected static $instance = null;

private function __construct() {}

private function __clone() {}

private function __sleep() {}

private function __wakeup() {}

public static function getInstance()
{
if (!self::$instance instanceof self) {
self::$instance = new self();
self::$instance->connect();
}

return self::$instance;
}
}

Factory 工厂模式

工厂模式是另一种常用的模式,它根据参数的不同返回不同类的实例

定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类

Factory.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Factory
{
public static function getDb($type = 'mysql')
{
$connection = null;
$type = strtolower($type);
switch ($type) {
case 'mongo':
$connection = Mongo::getInstance();
break;
case 'pgsql':
$connection = Pgsql::getInstance();
break;
case 'mysql':
default:
$connection = Mysql::getInstance();
}
return $connection;
}
}

Prototype 原型模式

有些时候,部分对象需要被初始化多次。创建一个原型然后克隆它,比正常创建一个对象 (new Foo ())会更节省开销

BookPrototype.php 抽象原型类
1
2
3
4
5
6
7
8
abstract class BookPrototype
{
protected $title;

protected $author;

abstract public function __clone();
}
NovelPrototype.php 子原型类
1
2
3
4
5
6
class NovelPrototype extends BookPrototype
{
protected $author = 'LiLuoao';

public function __clone() {}
}
1
2
3
4
5
6
$novelPrototype = new NovelPrototype();

for ($i = 0; $i < 10; $i++) {
$book = clone $novelPrototype;
$book->setTitle('Adult Book No ' . $i);
}

Builder 建造者模式

建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

  1. 对象的生产需要复杂的初始化,比如给一大堆类成员属性赋初值,设置一下其他的系统环境变量。使用建造者模式可以将这些初始化工作封装起来。
  2. 对象的生成时可根据初始化的顺序或数据不同,而生成不同角色。

如果我们想创造出一个英雄类,我们通过实例化时设置的属性不同,让一个是射程远血量少的射手,一个是射程短血量厚的坦克:

Hero.php 英雄类
1
2
3
4
5
6
class Hero
{
public $hp;

public $range;
}
Builder.php 抽象建造者类
1
2
3
4
5
6
7
8
9
10
11
12
13
abstract class Builder
{
public $hero;

public abstract function setHp();

public abstract function setRange();

public function __construct(Hero $hero)
{
$this->hero = $hero;
}
}
ADCarryBuider.php 射手建造者
1
2
3
4
5
6
7
8
9
10
11
class ADCarryBuider extends Builder
{
public function setHp()
{
$this->hero->hp = 2200;
}

public function setRange(){
$this->hero->range = 575;
}
}
TankBuider.php 坦克建造者
1
2
3
4
5
6
7
8
9
10
11
class TankBuider extends Builder
{
public function setHp()
{
$this->hero->hp = 4396;
}

public function setRange(){
$this->hero->range = 125;
}
}
Director.php 建造指挥者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Director
{
private $builder;

public function __construct(Builder $builder)
{
$this->builder = $builder;
}

public function built()
{
$this->builder->setHp();
$this->builder->setRange();
}
}
1
2
3
4
5
6
//实例化一个射手建造者
$adcBuilder = new ADCarryBuider(new Hero);
//实例化指挥者并建造
(new Director($adcBuilder))->built();
//得到射手
$adc = $adcBuilder->getHero();