您的位置:首页 > 其它

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

2015-02-17 18:36 471 查看
<?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();
?>


本文出自 “一切皆有可能” 博客,请务必保留此出处http://noican.blog.51cto.com/4081966/1614770
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: