<?php /** * 1.3 抽象工厂模式 * 解决的问题: * 如何解决多个类实例化对象的问题。 * 解决的方案: * 提供一个创建一系列相关或相互依赖对象的 * 接口,而无需指定它们具体的类。 * 该模式包含四种角色: * 1. 抽象产品角色(两个或多个) * 职责:同工厂方法模式 * 2. 具体产品角色 * 职责:同工厂方法模式 * 3. 抽象工厂角色 * 职责:同工厂方法模式 * 4. 具体工厂角色 * 职责:同工厂方法模式 * 优点: * 1. 易于交换产品系列,由于工厂类在 * 一个应用中只需要在初始化的时候 * 出现一次,这就使得改变一个应用 * 的具体工厂变得非常容易,它只需 * 要改变具体工厂即可使用不同的产 * 品配置。 * 2. 使具体的创建实例过程与客户端分 * 离,客户端时通过它们的抽象接口 * 操纵实例,产品的具体类名也被具 * 体工厂的实现分离,不会出现在客 * 户代码中。 * 缺点: * 1. 当增加新的产品时,就要增加抽象 * 产品角色、具体产品角色、具体工 * 厂角色三个角色(类),另外至少 * 还要修改抽象工厂角色。 * 2. 在客户端很多的话,如果要进行产 * 品的切换,那么就会出现大批量的 * 改动。 * 使用场景: * 1. 一个系统要独立于它的产品的创建 * 、组合和表示时。 * 2. 一个系统要由多个产品系列中的一 * 个来配置时(比如数据库)。 * 3. 当你要强调一系列相关产品对象的 * 设计以便进行联合使用时。 * 4. 当你提供一个产品类库,而只想显 * 示它们的接口而不是实现时。 * */ /** * 以两种数据库产品来举例 */ //第一种抽象产品类 abstract class User{ abstract public function addUser(); abstract public function queryUser(); } //第二种抽象产品类 abstract class Department{ abstract public function addDeptmt(); abstract public function queryDeptmt(); } /** * 第三种抽象产品类 * . * . * . * . * 第N种抽象产品类 */ //第一种抽象产品类的具体产品类 //用户的添加和查询 //MysqlUser是抽象产品User的第一个具体产品类 class MysqlUser extends User{ public function addUser(){ echo ‘在Mysql数据库中添加一个用户‘; } public function queryUser(){ echo ‘在Mysql数据库中查询某个用户信息‘; } } //MongodbUser是抽象产品User的第二个具体产品类 class MongodbUser extends User{ public function addUser(){ echo ‘在MongoDB数据库中添加一个新用户‘; } public function queryUser(){ echo ‘在MongoDB数据库中查询某个用户信息‘; } } //第二种抽象产品类的具体产品类 //部门的添加和查询 //MysqlDeptmt是抽象产品Department的第一个具体产品类 class MysqlDeptmt extends Department{ public function addDeptmt(){ echo ‘在Mysql数据库中添加一个新部门‘; } public function queryDeptmt(){ echo ‘在Mysql数据库中查询某个部门信息‘; } } //MongodbDeptmt是抽象产品Department的第二个具体产品类 class MongodbDeptmt extends Department{ public function addDeptmt(){ echo ‘在MongoDB数据库中添加一个新部门‘; } public function queryDeptmt(){ echo ‘在MongoDB数据库中查询部门信息‘; } } //抽象工厂角色 abstract class DBFactry{ //因为是有两个抽象产品,多以与之对应的 //应该有两个创建响应产品对象的方法。 abstract static public function createUser(); abstract static public function createDept(); } /** * 具体工厂角色 * 每个抽象产品角色对应的具体产品角色都有 * 一个与之对应的具体工厂角色,也就是说抽 * 象产品对应多少个具体的产品,就有多少个 * 具体产品工厂角色与之对应。因为抽象工厂 * 方法对应的是多个产品,所以可以在具体工 * 厂中返回多个具体产品的实例对象。 */ //MysqlDBFactry是与具体产品MysqlUser和 //MysqlDeptmt对应的具体工厂类。 class MysqlDBFactry extends DBFactry{ public static function createUser(){ return new MysqlUser(); } public static function createDept(){ return new MysqlDeptmt(); } } //MongoDBFactry是与具体产品MongodbUser和 //MongoDeptmt对应的具体工厂类。 class MongoDBFactry extends DBFactry{ public static function createUser(){ return new MongodbUser(); } public static function createDept(){ return new MongodbDeptmt(); } } /** * 使用简单工厂改进抽象工厂 * 改进后的优点: * 1. 当切换数据库时,客户端无需任何 * 修改。 * 缺点: * 如果再新增一种数据库,那么就要添加 * 一个具体产品类,修改简单工厂中相关 * 的switch语句。 * */ class SimpleFactry{ //$db:作为数据库切换变量 private static $db=‘mysql‘; public static function createUser(){ switch (self::$db) { case ‘mysql‘: $obj=new MysqlUser(); break; case ‘mongodb‘: $obj=new MongodbUser; break; } return $obj; } public static function createDept(){ switch(self::$db){ case ‘mysql‘: $obj=new MysqlDeptmt(); break; case ‘mongodb‘: $obj=new MongodbDeptmt(); break; } return $obj; } } /** * 利用反射技术进一步改进抽象工厂模式 */ class ReflctSmplFactry{ private static $db=‘Mysql‘; public static function createUser(){ $className=self::$db.‘User‘; $reflct=new ReflectionClass($className); return $reflct->newInstance(); } public static function createDept(){ $className=self::$db.‘Deptmt‘; $reflct=new ReflectionClass($className); return $reflct->newInstance(); } } //正常抽象工厂模式的客户端 $factry=MysqlDBFactry::createDept(); $factry->addDeptmt(); $factry->queryDeptmt(); $f2=MongoDBFactry::createUser(); $f2->addUser(); $f2->queryUser(); // 使用简单工厂改进后的抽象工厂模式的客户端 $fcty=SimpleFactry::createUser(); $fcty->addUser(); $fcty->queryUser(); $fcty2=SimpleFactry::createDept(); $fcty2->addDeptmt(); $fcty2->queryDeptmt(); // 使用反射技术改进后的抽象工厂模式的客户端 $fctry=ReflctSmplFactry::createUser(); $fctry->addUser(); $fctry->queryUser(); $fctry2=ReflctSmplFactry::createDept(); $fctry2->addDeptmt(); $fctry2->queryDeptmt(); ?>
时间: 2024-10-06 14:18:53