设计模式之工厂模式分为三种:简单工厂、工厂方法和抽象工厂模式,有时也把简单工厂和工厂方法这两种归为一类。工厂模式属于“创建”型的设计模式,顾名思义用来实例化对象,调用者不需要关心对象的具体创建过程,以达到解耦的目的。
在大多数面向对象的语言中,实例化对象基本上都是 new ClassA() 这样创建实例,有两个原因不建议这么做:1.上层使用者没有和对象的创建过程隔离,导致代码耦合度高 2.创建对象实例的过程可能比较复杂,比如一些前置的过程。所以把这个创建过程交给工厂方法,调用者不用关心实例是怎么创建的。
工厂是生产产品的,这里产品指的就是具体的实例。简单工厂和抽象工厂设计模式都是为了解决类的实例化,避免 new XX() 带来的代码耦合。
简单工厂模式
简单工厂模式可以通过一个工厂方法,或者说一个函数,比如传入一个参数,工厂方法根据这个参数返回具体类的实例。它相当于多了一层封装,你只要关心需要什么实例,它就返回什么实例,而不用直接实例化,实例化的过程交给了工厂方法。
Laravel 中一个数据库连接的工厂类:
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
protected
function
createConnection
(
$driver
,
$connection
,
$database
,
$prefix
=
''
,
array
$config
=
[
]
)
{
if
(
$this
->
container
->
bound
(
$key
=
"db.connection.{$driver}"
)
)
{
return
$this
->
container
->
make
(
$key
,
[
$connection
,
$database
,
$prefix
,
$config
]
)
;
}
switch
(
$driver
)
{
case
'mysql'
:
return
new
MySqlConnection
(
$connection
,
$database
,
$prefix
,
$config
)
;
case
'pgsql'
:
return
new
PostgresConnection
(
$connection
,
$database
,
$prefix
,
$config
)
;
case
'sqlite'
:
return
new
SQLiteConnection
(
$connection
,
$database
,
$prefix
,
$config
)
;
case
'sqlsrv'
:
return
new
SqlServerConnection
(
$connection
,
$database
,
$prefix
,
$config
)
;
}
throw
new
InvalidArgumentException
(
"Unsupported driver [$driver]"
)
;
}
|
这里根据配置文件数据库驱动的配置,返回对应数据库的连接对象的实例。
简单工厂模式符合单一职责原则,也就是每个类只做一件事情,但不符合开放封闭原则,每次增加和减少一个对象都要对简单工厂进行修改,不能做到很好的扩展。
抽象工厂模式
抽象工厂模式在简单工厂模式基础上,多了一层抽象工厂接口,它的思想是,假如有多个工厂生产同样的产品,他们有同样的行为,那么把这些产品的创建行为抽象出来,每个工厂实现这个抽象接口。
适用场景
有多个工厂,生产同一类型的产品,如下所示:
工厂1
- 产品1
- 产品2
- 产品3
工厂2
- 产品1
- 产品2
- 产品3
以 Mac 系统和 Windows 系统为例,都有创建 button 和创建 border 功能,这两个工厂都可以生产 button 和 border,那么把创建这两个产品的方法抽象出来,这个抽象出来的方法叫做抽象工厂类,两个工厂都要实现这个抽象类。
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
|
abstract
class
AbstractFactory
{
abstract
public
function
CreateButton
(
)
;
abstract
public
function
CreateBorder
(
)
;
}
class
MacFactory
extends
AbstractFactory
{
public
function
CreateButton
(
)
{
return
new
MacButton
(
)
;
}
public
function
CreateBorder
(
)
{
return
new
MacBorder
(
)
;
}
}
class
WinFactory
extends
AbstractFactory
{
public
function
CreateButton
(
)
{
return
new
WinButton
(
)
;
}
public
function
CreateBorder
(
)
{
return
new
WinBorder
(
)
;
}
}
class
Button
{
}
class
Border
{
}
class
MacButton
extends
Button
{
function
__construct
(
)
{
echo
'MacButton is created'
.
"\n"
;
}
}
class
MacBorder
extends
Border
{
function
__construct
(
)
{
echo
'MacBorder is created'
.
"\n"
;
}
}
class
WinButton
extends
Button
{
function
__construct
(
)
{
echo
'WinButton is created'
.
"\n"
;
}
}
class
WinBorder
extends
Border
{
function
__construct
(
)
{
echo
'WinBorder is created'
.
"\n"
;
}
}
?>
|
从工厂取出实例:
1
2
3
4
5
6
7
|
$type
=
'Mac'
;
//value by user.
if
(
!
in_array
(
$type
,
array
(
'Win'
,
'Mac'
)
)
)
die
(
'Type Error'
)
;
$factoryClass
=
$type
.
'Factory'
;
$factory
=
new
$factoryClass
;
$factory
->
CreateButton
(
)
;
$factory
->
CreateBorder
(
)
;
|