1.引言
在软件设计中,工厂模式是一种常用的设计模式,它用于创建对象的实例而不暴露实例化对象的具体逻辑。在PHP中,工厂模式有两种常见的实现方式:简单工厂模式和抽象工厂模式。简单工厂模式适用于较为简单的应用场景,而抽象工厂模式则提供了更高的扩展性。在本文中,我们将详细讲解这两种模式,通过实际的PHP代码示例来展示它们的实现方法和应用场景。
2. 核心概念
简单工厂模式(Simple Factory Pattern) :简单工厂模式是通过一个工厂类来创建对象,它根据不同的参数决定实例化哪个类。调用方只需要依赖工厂类,而不需要知道具体的实现类。
抽象工厂模式(Abstract Factory Pattern) :抽象工厂模式比简单工厂模式更加抽象,它通过一组工厂类来创建多个产品类别的对象。每个具体工厂类负责创建一类产品,并且工厂类本身和产品类都遵循抽象化设计,具有很高的可扩展性。
3. 应用场景
简单工厂模式:当创建对象的过程相对简单,且对象类型不多时,适用简单工厂模式。适用于需要选择不同产品类型但不想暴露复杂创建过程的场景。
抽象工厂模式:当系统中存在多个相关产品,并且产品的种类在未来可能会扩展时,使用抽象工厂模式。适用于跨多个产品族的对象创建场景,并且产品类别之间的变动不会影响已有的代码。
4. 实现步骤
1. 简单工厂模式
- 定义接口:创建一个共同的接口(如
Db接口),确保所有具体产品类实现该接口。 - 实现具体产品:实现具体的类(如
Mysql,Oracle)。 - 工厂类:创建一个工厂类(如
DbFactory),根据输入参数返回不同的产品实例。
/**
* 定义一个数据库的接口
*/
interface Db {
/**
* 定义一个链接数据库的接口方法
*
* @return mixed
* @author kx
*/
public function conn();
}
// 服务端生产
/**
* 定义一个mysql数据库实现db的接口
*/
class Mysql implements Db {
/**
* 实现链接方法
*
* @author kx
*/
public function conn()
{
echo "连接上mysql了";
}
}
/**
* 定义一个Oracle数据库
*/
class Oracle implements Db {
/**
* 实现链接方法
*
* @author kx
*/
public function conn()
{
echo "连接上Oracle了";
}
}
/**
* db简单工厂
*/
class DbFactory {
/**
* 创建数据库
*
* @param $dbType
* @return Mysql|Oracle
* @throws Exception
* @author kx
*/
public static function createDb($dbType) {
if ($dbType == "mysql") {
return new Mysql();
} elseif ($dbType == "oracle") {
return new Oracle();
} else {
throw new Exception("数据库类型错误");
}
}
}
//客户端调用
//只需要调用工厂,传入数据库类型,保证了Mysql、Oracle类不暴露给调用方
$mysql = DbFactory::createDb('mysql');
$mysql->conn();
$mysql = DbFactory::createDb('oracle');
$mysql->conn();
输出内容:
连接上mysql了连接上Oracle了
2. 抽象工厂模式
- 定义抽象产品接口:创建一个抽象接口(如
Db),定义所有数据库类的共同行为。 - 定义抽象工厂接口:创建一个工厂接口(如
DbFactory),声明创建产品的方法。 - 实现具体工厂和产品:创建具体工厂(如
MysqlFactory)和相应的产品类(如Mysql)。 - 扩展新产品:如需增加新类型的数据库,只需增加一个新的产品类和工厂类,而不需要修改现有代码。
/**
* 定义一个数据库的接口
*/
interface Db {
/**
* 定义一个链接数据库的接口方法
*
* @return mixed
* @author kx
*/
public function conn();
}
/**
* 定义一个数据库工厂接口
*/
interface DbFactory {
public function createDb();
}
// 服务端生产
/**
* 定义一个mysql数据库实现db的接口
*/
class Mysql implements Db {
/**
* 实现链接方法
*
* @author kx
*/
public function conn()
{
echo "连接上mysql了";
}
}
/**
* Mysql的工厂类
*/
class MysqlFactory implements DbFactory {
/**
* 实现Mysql创建
*
* @return Mysql
* @author kx
*/
public function createDb()
{
return new Mysql();
}
}
/**
* 定义一个Oracle数据库
*/
class Oracle implements Db {
/**
* 实现链接方法
*
* @author kx
*/
public function conn()
{
echo "连接上Oracle了";
}
}
/**
* OracleFactory工厂类
*/
class OracleFactory implements DbFactory {
/**
* 实现Oracle创建
*
* @return Oracle
* @author kx
*/
public function createDb()
{
return new Oracle();
}
}
// 新增sqlite,不用修改之前的代码,只需要新增两个类,一个实现Db,一个实现DbFactory
/**
* 实现Sqlite类
*/
class Sqlite implements Db {
/**
* 连接sqlite
*
* @author kx
*/
public function conn()
{
echo "连接Sqlite";
}
}
/**
* 实现SqliteFactory
*/
class SqliteFactory implements DbFactory {
/**
* 实现创建Db方法
*
* @return Sqlite
* @author kx
*/
public function createDb()
{
return new Sqlite();
}
}
//客户端调用
//需要不同的工厂类,如果需要新增类型,只需要拓展,不需要修改以前的代码
$fac = new MysqlFactory();
$db = $fac->createDb();
$db->conn();
$fac = new OracleFactory();
$db = $fac->createDb();
$db->conn();
$fac = new SqliteFactory();
$db = $fac->createDb();
$db->conn();
输出内容:
连接上mysql了连接上Oracle了连接Sqlite
5. 好处和不足
简单工厂模式
好处:
- 封装性强:客户端无需了解具体对象的创建细节。
- 易于使用:只需调用工厂类的静态方法即可创建对象,使用简单。
不足:
- 违反开闭原则:每次增加新的数据库类型时,都需要修改工厂类,违反了开闭原则。
- 不易扩展:随着产品类型的增加,工厂类的代码变得复杂且难以维护。
抽象工厂模式
好处:
- 符合开闭原则:每新增一个产品族,只需要增加对应的工厂类和产品类,无需修改现有代码。
- 灵活性高:可以根据不同需求创建不同类型的对象,且这些对象是相互兼容的。
不足:
- 实现较复杂:需要定义多个接口和工厂类,相比简单工厂模式,代码更为复杂。
- 不适用于简单场景:对于简单的对象创建,不需要如此复杂的结构。
6. 总结
简单工厂和抽象工厂模式是两种不同的设计模式,虽然都用于对象的创建,但它们的设计理念和适用场景有所不同。简单工厂模式适用于对象类型较为固定的场景,它实现简单但缺乏灵活性。而抽象工厂模式则为系统的扩展提供了更多的灵活性和可维护性,特别适用于需要创建一系列相互依赖或兼容的对象的场景。
在实际开发中,我们需要根据项目的复杂度、扩展性要求来选择合适的工厂模式。简单工厂可以快速实现一些基础功能,而抽象工厂则在产品种类多、需要扩展时更加合适。