设计模式之创建型模式―― 1.3 抽象工厂模式

<?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();
?>


你可能感兴趣的:(设计模式,抽象工厂模式)