PHP中的设计模式 <持续更新中...>

420 查看


工厂模式

/* 工厂模式代码片段*/
class Employee{

    private static $type = array('minion', 'wellcon', 'student');

    public static function recuit($name)
    {
        $num = rand(1, count(Employee::$type)) - 1 ;
        $class = Employee::$type[$num]; // 访问静态属性要加$符
        return new $class($name);
    }
}
$boss = new Boss();
$boss->addEmployee(Employee::recuit('hard')); // 静态方法生成实例对象,作为addEmployee函数的参数

工厂就是负责生成对象的类或方法

class Demo {

    public function getInstance($type)
    {
        switch($type){
            case '1':
                return new A();
                break;
            case '2':
                return new B();
                break;
            case '3':
                return new C();
                break;

        }
    }
}

工厂模式,是把创造者类和要生产的类分开,创建者是个工厂类,定义了用于生产产品对象的方法

abstract class commonMessage {

    abstract function getInstance();
}

class A extends commonMessage{

    public function getInstance()
    {
        return new A();
    }
}

class B extends commonMessage{

    public function getInstance()
    {
        return new B();
    }
}

行程特殊的代码重复,不必要的子类话,为了工厂模式,而为创建类创建子类


抽象工厂模式

对于那些不必须要的子类模式,合并起来,通过一个类中多个方法就可以完成工厂输出

abstract class messageFactor
{

    abstract function getHeader();

    abstract function getMail();

    abstract function getMobile();

    abstract function getFooter();
}

class smudgeMo extends messageFactor
{

    public function getHeader()
    {
        return 'Header';
    }

    public function getMail()
    {
        return new Mail();
    }

    public function getMobile()
    {
        return new Mobile();
    }

    public function getFooter()
    {
        return 'Footer';
    }
}

class julylovinMo extends messageFactor
{

// 和上个子类相似
}

虽然减少了子类继承,但是耦合问题太严重,如果增加一个产品类型, 抽象函数和子类继承体,都需要增加对应的方法

abstract class factory{

    const APPT = 1;
    const TTD = 1;
    const CONTACT = 1;
    abstract function make($flag_int);
}

class mailModel extends factory{

    public function make($flag_int)
    {
        switch ($flag_int){

            case self::APPT:
                return new apptEncoder();
                break;

            case self::TTD:
                return new ttdEncoder();
                break;

            case self::CONTACT:
                return new contactEncoder();
                break;
        }


    }
}

紧凑型工厂模式,但是耦合度高,不利于维护


单例模式

全局变量将类捆绑于特定环境中,破坏了封装
特点:
preference 可以被任何对象调用,无需将对象作为参数传递
preference 不该保存在全局变量中
系统中不应超过一个preference对象,即只允许实例化一次

class Preference
    {

    static $instance;
    public $name;

    private function __construct()
    {

    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) // 控制了只有一个Preference实例对象
        {
            self::$instance = new Preference();
        }
        return self::$instance;
    }
}

$prf = Preference::getInstance(); // 任何地方可以获取Preference实例对象
$prf->setName('Julylovin');
echo $prf->getName(); // Julylovin

原型模式

用组合代替继承,抽象工厂模式有平行层次继承,会有耦合问题
使用clone关键词复制已经存在的产品, 具体产品本身,便成为自身生成的基础

class sea {
private $navigability = 0 ; //可航行
public function __construct($navigability)
    {
        $this->navigability = $navigability;
    }
}
class earthsea extends sea{}
class plain{}
class earthplain extends plain{}
class forest{}
class earthforest extends forest{}
class factory{

    private $sea;
    private $plain;
    private $forest;

    public function __construct(sea $sea, plain $plain, forest $forest)
    {
        $this->sea = $sea;
        $this->plain = $plain;
        $this->forest = $forest;
    }

    public function getSea()
    {
        return clone $this->sea;// 只是引用对象,是同一个对象,并非两个对象
    }

    public function getPlain()
    {
        return clone $this->plain;
    }

    public function getForest()
    {
        return clone $this->forest;
    }
}

$earthInstance = new factory(new earthsea(1), new earthplain(), new earthforest()); //海域可航行
$earthInstance->getForest(); // new earthforest() 的实例

组合模式

组合模式有助于集合和组件之间关系建立模型
枪手(Archer)组合成军队(Arm),多个枪手可以增加军队的战斗力(bombardStrength)

abstract class unit {

    public function addunit(Unit $unit){
        // 阻止独立单元再次添加对象
        throw new unitException(get_class($unit).'is a leaf');
    }

    public function removeunit(Unit $unit){
        // 阻止独立单元删除添加对象
        throw new unitException(get_class($unit).'is a leaf');
    }
    abstract function bombardStrength();
}

class unitException extends Exception{}

class Archer extends unit {

    public function bombardStrength()
    {
        return 4 ;
    }
}

class Army extends unit{  //组合模式体

    private $units = array();

    public function addunit(Unit $unit)
    {
        if(in_array($unit, $this->units, true))
        {
            return ;
        }
        $this->units[] = $unit;
    }

    public function removeunit(Unit $unit)
    {
        $units = array();
        foreach ($this->units as $item)
        {
            if($item !== $unit)
            {
                $units[] = $item;
            }
        }
        $this->units = $units;
    }

    public function bombardStrength()
    {
        $ret = 0 ;
        foreach ($this->units as $unit)
        {
            $ret += $unit->bombardStrength();
        }
        return $ret;
    }
}

$SubArmy = new Army();
$SubArmy->addunit( new Archer());
$SubArmy->addunit( new Archer());
echo $SubArmy->bombardStrength(); // 8




装饰模式

组合模式用户聚合组件,装饰模式使用类似功能,改变组件具体功能
继承是共享父类特性的简单方法,所以当改变某些特性时,各种硬编码会出现在继承体
导致功能定义依赖于继承体,导致代码增多,导致代码重复

abstract class tile{

    abstract function get_wealth();
}

class plains extends tile {
    private $wealth = 2;
    public function get_wealth()
    {
        return $this->wealth;
    }
}

class polluted extends plains {
    public function get_wealth()
    {
        return parent::get_wealth()-2;
    }
}

class diamond extends plains{
    public function get_wealth()
    {
        return parent::get_wealth()+10 ;
    }
}
// 上图组合模式 不容易实现既是钻石地段又是污染地段的价值,常规做法,会建立类 diamond_polluted

 装饰模式是使用组合和委托,而不是单纯的继承
abstract class tile {
    abstract function getwealth();
}

class plains extends tile {
    private $wealth = 2;
    public function getwealth()
    {
        return $this->wealth;
    }
}

abstract class tile_decorate extends tile{
    protected $tile ; // 保护属性,便于子类和当前类当问
// 构造方法,接收实例对象,保存在tile属性中
    public function __construct(tile $tile)
    {
        $this->tile = $tile;
    }
}

class pollute_decorate extends tile_decorate {
    public function getwealth()
    {
        return $this->tile->getwealth()-4;
    }
}

class diamon_decorate extends tile_decorate {
    public function getwealth()
    {
        return  $this->tile->getwealth()+2;
    }
}

$tile = new plains();
echo $tile->getwealth();
$tile = new diamon_decorate(new plains());
echo  $tile->getwealth();
$tile = new pollute_decorate(new diamon_decorate(new plains())); // 组合成一个整体
echo $tile->getwealth();
// 多个组合及委托,极具灵活性


  多个装饰器串联起来,形成管道,便于创建过滤器,核心组件和装饰漆组合,对其流程进行过滤缓冲,压缩
class request_helper{}

abstract class process_request{
    abstract function process(request_helper $req);
}

class main_process extends process_request {
    public function process(request_helper $req)
    {
        echo __CLASS__."is processing \n";
    }
}

abstract class process_decorate extends process_request {

    protected $process_request;
    public function __construct(process_request $pro)
    {
        $this->process_request = $pro;
    }
}

class log_process extends process_decorate {
    public function process(request_helper $req)
    {
        print __CLASS__."is processing log \n";
        $this->process_request->process($req);
    }
}

class authenticate extends process_decorate {
    public function process(request_helper $req)
    {
        print __CLASS__."is processing authentication \n";
        $this->process_request->process($req);
    }
}

class structure_request extends process_decorate {
    public function process(request_helper $req)
    {
        print __CLASS__."is processing structure \n";
        $this->process_request->process($req);
    }
}

$process = new authenticate(new structure_request(new log_process(new main_process())));
$process->process(new request_helper());
// auth->struct->log->main

装饰模式一定是组合和继承同时使用
等同于__call 拦截方法,捕捉不存在的方法自动调用