php设计模式之三__工厂模式

工厂模式:

1. 特点:

工厂模式其实是一种类,为您提供一些创建对象的方法,通过该工厂可以,方便的创建不同的对象,不用去new,如果需要更改创建对象的类型,直接修改该工厂类即可,很好的遵循了开闭原则及单一责任原则等。

2. 分类:

根据抽象程度不同,分为,简单工厂模式、工厂方法模式、抽象工厂模式。

         1)简单工厂模式(静态工厂方法模式)

a.类图


b. 代码案例:

/**
      * 操作类
      * 因为包含有抽象方法,所以类必须声明为抽象类
      */
     abstract class Operation{
         abstract public function getValue($num1,$num2); 
     }
     /**
      * 加法类
      */
     class OperationAdd extends Operation {
         public function getValue($num1,$num2){
             return $num1+$num2;
         }
     }
     /**
      * 减法类
      */
     class OperationSub extends Operation {
         public function getValue($num1,$num2){
             return $num1-$num2;
         }
     }
     /**
      * 乘法类
      */
     class OperationMul extends Operation {
         public function getValue($num1,$num2){
             return $num1*$num2;
         }
     }
     /**
      * 除法类
      */
     class OperationDiv extends Operation {
         public function getValue($num1,$num2){
             try {
                 if ($num2==0){
                     throw new Exception("除数不能为0");
                 }else {
                     return $num1/$num2;
                 }
             }catch (Exception $e){
                 echo "错误信息:".$e->getMessage();
             }
         }
     }
     /**
     * 工程类,主要用来创建对象
     * 功能:根据输入的运算符号,工厂就能实例化出合适的对象
     *
     */
    class Factory{
        public static function createObj($operate){
            switch ($operate){
                case '+':
                    return new OperationAdd();
                    break;
                case '-':
                    return new OperationSub();
                    break;
                case '*':
                    return new OperationSub();
                    break;
                case '/':
                    return new OperationDiv();
                    break;
            }
        }
    }
    $test=Factory::createObj('/');
    $result=$test->getValue(23,10);
    echo $result;
  c.适用情况:工厂类负责创建的对象较少, 客户只需知道创建对象时传入的参数,无需知道如何创建对象。

 2)工厂方法模式:

a.类图

b代码示例:

/*
 *定义一个创建对象的接口,让子类决定哪个类实例化。
 *解决简单工厂模式中的封闭开放原则问题。 
 */
 abstract class Operation{
         abstract public function getValue($num1,$num2); 
     }
     /**
      * 加法类
      */
     class OperationAdd extends Operation {
         public function getValue($num1,$num2){
             return $num1+$num2;
         }
     }
     /**
      * 减法类
      */
     class OperationSub extends Operation {
         public function getValue($num1,$num2){
             return $num1-$num2;
         }
     }
     /**
      * 乘法类
      */
     class OperationMul extends Operation {
         public function getValue($num1,$num2){
             return $num1*$num2;
         }
     }
     /**
      * 除法类
      */
     class OperationDiv extends Operation {
         public function getValue($num1,$num2){
             try {
                 if ($num2==0){
                     throw new Exception("除数不能为0");
                 }else {
                     return $num1/$num2;
                 }
             }catch (Exception $e){
                 echo "错误信息:".$e->getMessage();
             }
         }
     }

// 此时将对象的创建抽象成一个接口。
abstract class Factory {
    abstract function create();
}
class FactoryAdd extends Factory{
    function create() {
        return  new OperationAdd;
    }
}
class FactorySub extends Factory {
    function create() {
        return new OperationSub;
    }
}
class FactoryMul extends Factory{
    function create(){
        return new OperationMul;
    }
}
class FactroyDiv extends Factory{
    function create (){
        return new OperationDiv;
    }
}
//客户端代码测试
class  Client {
    // 简单工厂里的静态方法
    function test() {
        $Factory =  new  FactoryAdd;
        $res = $Factory->create();
        echo $res->getValue(19,23).'<br>';
        
        $Factory =  new FactroyDiv;
        $res = $Factory->create();
        echo $res->getValue(23,22).'<br>';
    }
}
$f = new Client;
$f->test();
c.适用情况:当所创建的对象有较多,且将类的实例化交给子类实现。这种方式很好的符合了开闭原则。

3) 抽象工厂模式:

提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。该模式为一个产品族提供了 统一的创建接口。当需要这个产品族的某一系列的时候,可以为此系列的产品族创建一个具体的工厂类。

a.类图:

b.代码实现:

<?php  
//抽象工厂  
interface AnimalFactory {  
      
    public function createCat();  
    public function createDog();  
      
}  
  
//具体工厂  
class BlackAnimalFactory implements AnimalFactory {  
      
    function createCat(){  
        return new BlackCat();  
    }  
      
    function createDog(){  
        return new BlackDog();    
    }  
}  
  
class WhiteAnimalFactory implements AnimalFactory {  
      
    function createCat(){  
        return new WhiteCat();  
    }  
      
    function createDog(){  
        return new WhiteDog();  
    }  
}  
  
//抽象产品  
interface Cat {  
    function Voice();  
}  
  
interface Dog {  
    function Voice();     
}  
  
//具体产品  
class BlackCat implements Cat {  
      
    function Voice(){  
        echo '黑猫喵喵……';  
    }  
}  
  
class WhiteCat implements Cat {  
      
    function Voice(){  
        echo '白猫喵喵……';  
    }  
}  
  
class BlackDog implements Dog {  
      
    function Voice(){  
        echo '黑狗汪汪……';        
    }  
}  
  
class WhiteDog implements Dog {  
      
    function Voice(){  
        echo '白狗汪汪……';        
    }  
}  
  
//test case 
class Client {  
      
    public static function main() {  
        self::run(new BlackAnimalFactory());  
        self::run(new WhiteAnimalFactory());  
    }  
      
    public static function run(AnimalFactory $AnimalFactory){  
        $cat = $AnimalFactory->createCat();  
        $cat->Voice();  
          
        $dog = $AnimalFactory->createDog();  
        $dog->Voice();  
    }  
}  
Client::main();  
?>  
c.适用情况:

1>一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
2>这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
3> 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
4>系统提供一个产品类的库,所有的产品以同样的接口出现,从而使用客户端不依赖于实现

d.优缺点

好处:增加或替换产品族容易,分离了具体的类,利于产品的一致性。

不足:新的产品族扩展不易。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值