php设计模式之一工厂模式--简单工厂模式

最近在学习设计模式,很多地方还理解的不够。在这里记录一下自己学习的东西,方便自己以后查看和理解,同时也给正在学这部分的同学提供一点参考。

工厂模式的几种形态:

  1、简单工厂模式(Simple Factory) |又叫做  静态工厂方法模式(Static Factory Method)
  2、工厂方法模式(Factory Method) |又叫做 多态性工厂模式(Polymorphic Factory)
  3、抽象工厂模式(Abstract Factory) |又叫做 工具箱模式(ToolKit)

简单工厂模式, 简单工厂模式不属于23种常用面向对象设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。其实质是由一个工厂类根据传入     的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。  

  简单工厂模式有三个角色

    1、抽象角色

    2、具体角色

    3、工厂角色 : 负责获取某个具体角色的实例

代码示例一

<?php

/**
 * 一个事例
 *
 * 一个农场,要向市场销售水果
 * 农场里有三种水果 苹果、葡萄
 * 我们设想:1、水果有多种属性,每个属性都有不同,但是,他们有共同的地方 |  生长、种植、收货、吃
 *         2、将来有可能会增加新的水果、我们需要定义一个接口来规范他们必须实现的方法
 *         3、我们需要获取某个水果的类,要从农场主那里去获取某个水果的实例,来知道如何生长、种植、收货、吃
 */


/**
 * 虚拟产品接口类
 * 定义好需要实现的方法
 */

interface fruit{

    /**
     * 生长
     */
    public function grow();

    /**
     * 种植
     */
    public function plant();

    /**
     * 收获
     */
    public function harvest();

    /**
     * 吃
     */
    public function eat();
    
}


/**
 * 定义具体产品类 苹果
 * 首先,我们要实现所继承的接口所定义的方法
 * 然后定义苹果所特有的属性,以及方法
 */
class apple implements fruit{

    //苹果树有年龄
    private $treeAge;

    //苹果有颜色
    private $color;

    public function grow(){
        echo "grape grow";
    }

    public function plant(){
        echo "grape plant";
    }

    public function harvest(){
        echo "grape harvest";
    }

    public function eat(){
        echo "grape eat";
    }

    //取苹果树的年龄
    public function getTreeAge(){
        return $this->treeAge;
    }

    //设置苹果树的年龄
    public function setTreeAge($age){
        $this->treeAge = $age;
        return trie;
    }

}

/**
 * 定义具体产品类 葡萄
 * 首先,我们要实现所继承的接口所定义的方法
 * 然后定义葡萄所特有的属性,以及方法
 */
class grape implements fruit{


    //葡萄是否有籽
    private $seedLess;

    public function grow(){
        echo "apple grow";
    }

    public function plant(){
        echo "apple plant";
    }

    public function harvest(){
        echo "apple harvest";
    }

    public function eat(){
        echo "apple eat";
    }

    //有无籽取值
    public function getSeedLess(){
        return $this->seedLess;
    }

    //设置有籽无籽
    public function setSeedLess($seed){
        $this->seedLess = $seed;
        return true;
    }

}


/**
 *农场主类 用来获取实例化的水果
 *
 */
class farmer{

    //定义个静态工厂方法
    public static function factory($fruitName){
        switch ($fruitName) {
            case 'apple':
                return new apple();
                break;
            case 'grape':
                return new grape();
                break;
            default:
                throw new badFruitException("Error no the fruit", 1);
                break;
        }
    }
}

class badFruitException extends Exception{
    public $msg;
    public $errType;
    public function __construct($msg = '' , $errType = 1){
        $this->msg = $msg;
        $this->errType = $errType;
    }    
}


/**
 * 获取水果实例化的方法
 */
try{
    $appleInstance = farmer::factory('apple');
    var_dump($appleInstance);
}catch(badFruitException $err){
    echo $err->msg . "_______" . $err->errType;
}

代码示例二

<?php
//简单工厂方法
interface Math
{
    public function calculation( $x, $y );
}

//加法实现
class Sum implements Math
{
    public function calculation( $x, $y )
    {
        return $x + $y;
    }
}

//减法实现
class Sub implements Math
{
    public function calculation( $x, $y )
    {
        return $x - $y;
    }
}


//工厂方法
class Factory
{

    public static function doMath( $type )
    {
        switch( $type )
        {
            case "+":
                return new Sum();
                break;
            case "-":
                return new Sub();
                break;
        }
    }
}

$obj = Factory::doMath('-');
echo $obj->calculation( 1, 2 );

 一个工厂类Factory,根据访问传入的符号不同,去动态的实例化不同的类。这样我们就不需要自己去实例化类,无论用户要进行何种计算,只需要实例化时:Factory::doMath('-'),传入自己想要的计算符号即可。而不需要自己去实例化相应的计算类。并且

调用统一的计算方法calculation(1, 2),传入参数即可获得结果。这样看来,简单工厂方法确实很是方便。但是,简单工厂方法违背了设计模式的一个原则:开放与封闭原则

  什么是开放与封闭原则呢?简单的讲就是:程序对扩展来说是开放的,对修改来说是封闭的。本案例,如果我想加入一个乘法计算,那么很简单我再添加一个乘法的类,但是,我必须去修改Factory类的doMath方法,将我新加入的乘法计算添加进去,这样就破坏了原来的类,也就违背了封闭原则。这时,工厂方法就解决了简单工厂违背开放与封闭原则的问题

posted @ 2017-10-19 11:26  CandyChen  阅读(176)  评论(0)    收藏  举报