工厂模式
概念
工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。
好处
使用工厂模式的好处是,如果你想要更改所实例化的类名等,则只需要更改该工厂方法内容即可,不需要逐一寻找代码中具体实例化的地方(new 处)修改了。为系统结构提供灵活的动态扩展机制,减少了耦合。
分类
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
简单工厂模式
简单工厂模式又称静态工厂模式,之所以可以这么说,是因为简单工厂模式是通过一个静态方法来创建对象的
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
class DbMysql
{
public function conn()
{
echo "连接MySQL";
}
}
class DbSqlite
{
public function conn()
{
echo "连接SQLite";
}
}
class DbFactory
{
public static function createIns($type)
{
switch ($type)
{
case 'mysql':
return DbMysql();
break;
case 'sqlite':
return new DbSqlite();
break;
default:
throw new ErrorException('类型错误');
}
}
}
$mysql = DbFactory::createIns('mysql');
$mysql->conn();
$sqlite = DbFactory::createIns('sqlite');
$sqlite->conn();工厂方法模式
简单工厂模式实现了产品类的代码跟客户端代码的分离,但会有一个问题,优秀的代码是符合“开闭原则”如果你要加一个C类产品,你就要修改工厂类里面的代码,也就是说要增加条件语句如:switch–case。对于这个问题,接下来的工厂方法模式可以解决这个问题。
概念
工厂方法就是为配一个产品提供一个独立的工厂类,通过不同的工厂实例来创建不同的产品实例。
优点
- 拥有良好的封装性,代码结构清晰,对于每一个对象的创建都是有条件约束的。如:调用一个具体的产品对象,只需要知道这个产品的类名和约束参数就可以了,不用知道创建对象自身的复杂过程。降低模块之间的耦合度。
- 拥有良好的扩展性,新增一个产品类,只需要适当的增加工厂类或者扩展一个工厂类,如下面的例子中,当需要增加一个数据库Oracle的操作,则只需要增加一个Oracle类,工厂类不用修改任务就可完成系统扩展。
- 屏蔽产品类,这一特点非常重要,产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。
使用场景
- 支付宝、微信、银联的连接方式(connectMode),支付方式(payMode)。使用工厂模式,“客户”就不需要知道具体的链接方式和支付方式了,只需要调用connectMode和payMode即可。
- MySQL、SQL Server、Oracle等数据库的连接方式(connectMode)、查询方式(selectMode)等操作可以使用工厂模式进行封装。
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
//数据库操作接口
interface Db
{
public function conn();
}
class DbMysql implements Db
{
public function conn()
{
echo "链接MySQL";
}
}
class DbSqlite implements Db
{
public function conn()
{
echo "连接SQLite";
}
}
//工厂接口
interface Factory
{
public static function createIns();
}
class MysqlFactory implements Factory
{
public static function createIns()
{
return new DbMysql();
}
}
class SqliteFactory implements Factory
{
public static function createIns()
{
return new DbSqlite();
}
}
//客户端
$mysql = MysqlFactory::createIns();
$mysql->conn();
$sqlite = SqliteFactory::createIns();
$sqlite->conn();
抽象工厂模式
概念
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象,而且使用抽象工厂模式还要满足以下条件:
- 系统中有多个产品族,而系统一次只可能消费其中一族产品
- 同属于同一产品族的产品可以使用
- 产品族:位于不同产品等级结构中,功能相关联的产品组成的家族。下面例子的汽车和空调就是两个产品树,奔驰C200+格力某型号空调就是一个产品族,同理,奥迪A4+海尔某型号空调也是一个产品族。
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
//汽车(抽象产品接口)
interface AutoProduct
{
public function dirve();
}
class AudiA4Product implements AutoProduct
{
public function dirve()
{
echo '奥迪A4';
}
}
class BenzC200Product implements AutoProduct
{
public function dirve()
{
echo '奔驰C200';
}
}
//空调(抽象产品接口)
interface AirCondition
{
public function blow();
}
class GreeAirCondition implements AirCondition
{
public function blow()
{
echo '格力';
}
}
class HaierAirCondition implements AirCondition
{
public function blow()
{
echo '海尔';
}
}
//工厂接口
interface Factory
{
public static function getAuto();
public static function getAirCondition();
}
//工厂A 奥迪A4+海尔空调
class AFactory implements Factory
{
public static function getAuto()
{
return new AudiA4Product();
}
public static function getAirCondition()
{
return new HaierAirCondition();
}
}
//工厂B 奔驰+格力
class BFactory implements Factory
{
public static function getAuto()
{
return new BenzC200Product();
}
public static function getAirCondition()
{
return new GreeAirCondition();
}
}
//客户端
//A工厂制作车
$auto_carA = AFactory::getAuto();
$auto_airA = AFactory::getAirCondition();
//奥迪+空调
$auto_carA->dirve();
$auto_airA->blow();
三种工厂模式的比较
- 简单工厂:用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
- 工厂方法:用来生产同一等级结构中的固定产品。(支持增加任意产品)
- 抽象工厂:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)