您的位置:首页 > 其它

简单工厂模式 单例工厂模式 工厂方法模式 抽象工厂模式 原型模式

2016-09-09 14:59 447 查看
首先,我们需要了解一下什么是工厂模式,工厂模式就是用来产生对象的类或方法,包括简单工厂模式,单例工厂,工厂方法模式,抽象工厂方法和原型工厂

1.简单工厂模式

简单工厂模式一般都是通过静态方法去产生对象的,可以产生任意对象。

示例代码如下:

class simpleFactory{
public static function getInstance($classname){
return new $classname();
}
}


2.单例工厂

通过单例工厂产生的对象能被其他对象全部访问,同时也避免了如全局变量般容易被覆写的风险

示例代码:

class singleFactory{
public static function getInstance($class){        if(!isset(self::$object[$class])||!self::$object[$class] instanceof $class ){
return self::$object[$class]=new $class();
}
return self::$object[$class];
}
}


3.工厂方法模式

假设我们现在有一个抽象工厂类company(把它当做一个公司),该类定义了一个工厂方法用来生产product1。

abstract class Company{
abstract function getProduct1();
}


在现实生活中,一个产品一般都会对应着几个型号,这里定义了接口product1用来实现多态

interface product1{
function getProduct1Type();
}


假设产品1有两种型号,那么具体的类定义如下:

class product1_1 implements product1{
function getProduct1Type(){
echo "1_1";
}
}
class product1_2 implements product1{
function getProduct1Type(){
echo "1_2";
}
}


一个公司要生产产品,还需要一个生产计划,即具体工厂类,代码如下:

class plan1 extends Company{
function getProduct1(){
$obj=new product1_1();
return $obj;
}
}
class plan2 extends Company{
function getProduct1(){
$obj=new product1_2();
return $obj;
}
}


到目前为止,我们就有了一个产品接口,这个接口有两个实现子类,还有一个抽象工厂接口,同样的这个抽象工厂接口也有两个具体工厂子类实现。

到这里,我们就可以看出工厂方法模式的好处,如果需要扩展产品型号,则只需要添加product1接口的具体实现(添加新产品),然后再增加一个具体工厂类(加入生产计划),而无需修改原代码,实现了横向的扩展。

在运用中,需要通过系统配置来决定实例化哪个具体创建者(使用哪个生产计划)。在这里展示一下具体的做法:

首先定义一个config 类,类中包含作为配置的静态变量

class config{
static $plan='plan1';
}


配置类

然后定义一个AppConfig类,这是一个标准的单例,可以全局访问,用于根据config类中的配置去实例化具体创建者(长度过截不下这里直接贴代码)

class Appconfig{
private static $app;
public $plan;
private function __construct(){
$this->init();
}
private function init(){
switch(config::$plan){
case'plan1':$this->plan=new plan1();break;
case'plan2':$this->plan=new plan2();break;
}
public static function getInstance(){
if(!isset($app) || $app instanceof Appconfig){
self::$app=new Appconfig();
}
return self::$app;
}
public function getPlan(){
return $this->Plan;
}
}
$obg=Appconfig::getInstance();
$obg->getPlan()->getProduct1();


通过修改config中的plan参数,我们就可以切换实例化的具体创建者(改变计划)

在现实生活中,一个公司很少只生产一种类型的产品,假设这个公司现在想生产新的产品来丰富自己的产品体系,又该怎么做呢?那么是时候介绍下一种模式——抽象工厂模式。

4.抽象工厂模式

上文所说的新产品,同样的也可能需要有多种型号来适应市场的需求,同样的,按照我们上面的思路,添加一个新产品能实现产品多样化的产品接口(新的产品接口),和具体的生产计划(具体工厂类),所以我们需要做的有这么几件事:在company抽象工厂类中添加:getProduct2()方法(抽象工厂类中包括应该所有工厂方法),并添加新的具体工厂类;添加一个新的产品接口product2;添加几个产品类去实现该接口,如product2_1,product2_2;添加具体创建者类,如plan3类,按照上面的代码去添加。

修改后代码:

abstract class Company{
abstract function getProduct1();
abstract function getProduct2();
}
interface product2{
function getProduct2Type();
}
class product2_1 implements product1{
function getProduct1Type(){
echo "2_1";
}
}
class product2_2 implements product1{
function getProduct1Type(){
echo "2_2";
}
}
class plan1 extends Company{
function getProduct1(){
$obj=new product1_1();
$obj=new product2_1();
return $obj;
}
}
class plan2 extends Company{
function getProduct1(){
$obj=new product1_2();
$obj=new product2_2();
return $obj;
}
}


在这里我们也能看到采用设计模式来设计代码所能带来的扩展方面的优势。但是到这里也许有人已经想到了一个问题,当产品日益增加,生产计划肯定越来越多,这意味着我们需要定义很多具体创建者类(制定很多生产计划),想到这就想狗带了。为了减少具体创建者的创建,该亮出大宝剑了——原型模式

5.原型模式

现在演示如何通过原型模式来对抽象工厂模式进行进一步的优化

class plan extends Company
{
private $product1;
private $product2;
public function __construct(product1 $p1, product2 $p2)
{
$this->product1 = $p1;
$this->product2 = $p2;
}
function getProduct1()
{
return clone $this->product1;
}
function getProduct2(){
return clone $this->product2;
}
}
$c=new plan(new product1(),new product2());
$a=$c->getProduct1();
$b=$c->getProduct2();


原型模式的思路是在初始化的时候就保存了具体产品类,然后在需要生产对象的时候通过clone已经存在的产品去产生对象,利用该模式可以用组合代替继承,提高了代码的灵活性,减少了创建的类的数量,但需要注意的一点是如果产品类属性里面包含对象属性,一般我们需要进行深克隆,关于deep clone和shallow clone的东西由于不是本篇文章的重点,请不清楚的读者自己去google一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐