PHP设计模式之抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。

常规写法


demo1.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
25
26
27
28
29
30
31
32
33
<?php
header('Content-Type:text/html; charset=utf-8');

abstract class Image{
abstract public function getWidth();
abstract public function getHeight();
}

class PNG extends Image{
public function getWidth(){
return 'PNG长度为100';
}
public function getHeight(){
return 'PNG高度为200';
}
}

class GIF extends Image{
public function getWidth(){
return 'GIF长度为100';
}
public function getHeight(){
return 'GIF高度为200';
}
}

$png = new PNG();
echo $png->getWidth();

echo '<br />';

$gif = new GIF();
echo $png->getHeight();

我们会发现demo1.php调用相应的类都很麻烦,对客户端的调用提高了要求。如果只提供一种入口,我们无所谓插入任意的图片类型,那么他都会在内部创建相应的对象,那么在客户端的调用就会非常的方便。

抽象工厂模式

多个产品类别使用抽象工厂模式

demo2.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<?php
header('Content-Type:text/html; charset=utf-8');

abstract class Image{
abstract public function getWidth();

abstract public function getHeight();
}

class PNG extends Image{
public function getWidth(){
return 'PNG长度为100';
}

public function getHeight(){
return 'PNG高度为200';
}
}

class GIF extends Image{
public function getWidth(){
return 'GIF长度为100';
}

public function getHeight(){
return 'GIF高度为200';
}
}

abstract class Factory{
abstract public function getMessage();
abstract public function getImage();
abstract public function getDown();
}

abstract class Down{
abstract public function getInfo();
}

class Down_PNG extends Down{
public function getInfo(){
return '下载PNG图片';
}
}

class Down_GIF extends Down{
public function getInfo(){
return '下载GIF图片';
}
}

class Factory_PNG extends Factory{
public function getMessage(){
return '您将要处理PNG,是否要处理呢?';
}
public function getImage(){
return new PNG();
}
public function getDown(){
return new Down_PNG();
}
}

class Factory_GIF extends Factory{
public function getMessage(){
return '您将要处理GIF,是否处理呢?';
}
public function getImage(){
return new GIF();
}
public function getDown(){
return new Down_GIF();
}
}


$png = new Factory_PNG();
echo $png->getMessage();
echo $png->getImage()->getWidth();
echo $png->getDown()->getInfo();

echo '<br />';

$gif = new Factory_GIF();
echo $gif->getMessage();
echo $gif->getImage()->getHeight();
echo $gif->getDown()->getInfo();

工厂方法模式
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建
多个。

一个使用抽象工厂模式的项目类图

demo3.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
header('Content-Type:text/html; charset=utf-8');

// 面向接口编程,这是一个接口,抽象类,用于规范业务层子类实现
abstract class AUser{
abstract public function selectUser(); // 查找
abstract public function updateUser(); // 修改
abstract public function deleteUser(); // 删除
abstract public function addUser(); // 新增
}

// 这是一个业务层,实现接口即可
class UserAction extends AUser{
public function selectUser(){
return '查找用户';
}

public function updateUser(){
return '修改用户';
}

public function deleteUser(){
return '删除用户';
}

public function addUser(){
return '新增用户';
}
}

// 工厂,用来生产各个产品的业务层对象
// 每个对象,可以使用单例模式,让他在整个流程中只保持一个实例
class Factory{
static public function getUser(){
return new UserAction();
}
}

// 用于客户端直接调用的类
class User{
private $obj;

public function __construct(){
$this->obj = Factory::getUser();
}

public function selectUser(){
return $this->obj->selectUser();
}

public function updateUser(){
return $this->obj->updateUser();
}

public function deleteUser(){
return $this->obj->deleteUser();
}

public function addUser(){
return $this->obj->deleteUser();
}
}

$user = new User();
echo $user->selectUser();
echo '<br />';
echo $user->addUser();