php-设计模式

设计模式本质上就是一种模式,只要了解每个模式个什么意思和作用就行,下面的代码例子也是为了方便理解,所以写的尽量简洁明了

1.单例模式 

  说明:某一个类全局只存在一个实例,并且不会被创建副本,因为不能被实例化了所以需要为外部提供一个获取实例的入口(一个静态方法)

  作用:(1)在一次运行中,不会被实例化多次可以减少内存的开销。

     (2)以数据库为例,只实例化一次还可以省去链接,断开等重复动作

     (3)因为只有一个实例,可以全局的控制配置信息

  实现:

php
class Single
{
    static private $instance;                            //实例
    private $conf;                                       //配置
    public $param;
    private function __construct($conf)                  //防止new
    {
        $this->conf = $conf;
    }
    private function __clone() {}                        //防止clone
    private function __sleep() {}                        //防止序列化
    
    static public function getInstance($conf)
    {
        if (! self::$instance)
        {
            self::$instance = new self($conf);
        }
        return self::$instance;
    }
}

//测试
$s1 = Single::getInstance(array());
$s2 = Single::getInstance(array());

$s1->param = 's1';
echo $s1->param;                                            //s1
echo $s2->param;                                            //s1

$s2->param = 's2';
echo $s1->param;                                            //s2
echo $s2->param;                                            //s2

?>

 

2.工厂模式

  说明:当需要一个实例的不需要new,直接属于置顶参数从工厂模式中调取就行了

  作用:(1)便于管理,易于扩展

     (2)外部不需要关心类的名称和文件位置,只要传入对应编号就行了

  实现:

php

class class1{};
class class2{};
class class3{};

class Factory
{
    private static $classes = [                         //可返回类
        1 => 'class1',
        2 => 'class2',
        3 => 'class3',
    ];
    static public function create($num)
    {
        if (isset(self::$classes[$num]))
        {
            return new self::$classes[$num]();
        }
        return false;
    }
}

$class = Factory::create(1);

?>

3.观察者模式

  说明:多个观察者观察一个主题对象,当主题对象发生改变的时候(这里只是指一个触发条件),会通知观察者让观察者(其实就是轮询去执行观察者的一个function)

  作用:看起来可能还是模模糊糊的,但看一下代码就能理解了,本质上很简单。举个例子假如我是个主题对象,我进门是一个触发条件,灯就打开了(灯是个观察者),电视就打开了(电视是个观察者)等等。。  这里还是看你注册了多少个观察者

在项目中,我们会在用户注册后还有有一系列动作(比如发站内信,发新人券什么的),可以把这些动作注册成观察者,观察到用户注册之后自动就只行了

  实现:

php

//这里可以用接口类限制下必须实现哪些方法,为了看起来简洁些就不整那些没用的了
class Action
{
    private $observers = [];
    
    //注册一个观察者
    public function attach($observer)
    {
        $this->observers[] = $observer;
    }
    
    //注销一个观察者
    public function detach($observer)
    {
        $k = array_search($observer, $this->observers);
        if ($k) unset ($this->observers[$k]);
    }
    
    //通知
    public function notify()
    {
        foreach ($this->observers as $observer)
        {
            $observer->update();
        }
    }
}

//观察者们
class Observer1
{
    function update(){echo 'Observer1';}
}
class Observer2
{
    function update(){echo 'Observer2';}
}

$action = new Action();
$action->attach(new Observer1());
$action->attach(new Observer2());
$action->notify();
?>

  补充(个人观点):我觉得叫观察者不是很准确,因为从实现来看并不是观察者主动触发的,而是被通知过才会有动作。他们也并没有执行观察这个动作。如果真是想完成观察这个动作我能想到的也就只能一直while了,while的条件可以用指针指向主题对象的某一个特征值,观察主题有没有变化。但这样开销大了。

 

4.适配器模式

  说明:可以当做一个中间件,对以前的对象再二次处理一下形成一个新接口

  作用:为了满足新的需求,要从老接口衍生出新的接口,为了省去大量重复代码和灵活性新接口会复用老接口代码,并做二次处理。假如我们以前有三个接口,分别是炒饭、炒面、炒粉。最近发现用户喜欢吃肥牛,我们就加了三个新品肥牛炒饭、肥牛炒面、肥牛炒粉。如果把所有老接口都改一下代价就比较大了,而且如果还是有客户点炒饭,炒面 我们还要考虑兼容性。所以如果有用户点肥牛炒饭 我们就调老接口生产一个炒饭然后在往里加肥牛就好了(说起来比较绕,其实原理很简单 看一下代码就明白了)

  实现:

php
class Rice
{
    public function dosomething()
    {
        return 'fry rice';                                                      // 炒饭
    }
}

class Noodles
{
    public function dosomething()
    {
        return 'fry noodles';                                                   //炒面
    }
}

class Adapter                                                                  //适配器
{
    private $obj;
    public function __construct($obj) 
    {
        $this->obj = $obj;
    }
    public function dosomething()
    {
        $res = $this->obj->dosomething();
        return $res . ' add fat cattle';                                        //加肥牛
    }
}
    
$adapter1 = new Adapter(new Rice());
$adapter2 = new Adapter(new Noodles());
echo $adapter1->dosomething();                                                  //fry rice add fat cattle  
echo $adapter2->dosomething();                                                  //fry noodles add fat cattle
?>

 

5.策略模式(这个没搞懂他的意义)

  说明:可以根据当前环境选择自己需要的功能,自己需要使用哪种方法,就直接new哪个对象了。那些对象也可以交给工厂模式管理

  作用:主要是为了防止下文使用 if...else 或 switch...case 所带来的复杂性和臃肿性。我之前一直没搞懂是咋就做到不用if..else了,一直觉得这个像脱裤子放屁(我的理解的不深,可能过个一两年我就意识到他的美好了,到时候我把这里删掉),看代码吧

  实现:

php
//先简单的说明一下,这个例子我想实现两个数字相加,这里我就直接写成方法了,方便一些。
//首先是传统的方法
$num1 = 1;
$num2 = 2;
function cal($num1, $num2, $oper)
{
    //$oper是符号,根据符号判断用户想做什么,这里不就好多if..else了嘛
    if ($oper == '+')
    {
        return $num1 + $num2;
    }
    else if ($oper == '-')
    {
        return $num1 - $num2;
    }
    else
        return false;
}

//我想让两个数字相加,所以我传的加号
echo cal($num1, $num2, '+');      

//-------------------------------------------------------分割线-------------------------------------------------------

//现在用策略模式
function add($num1, $num2)
{
    return $num1 + $num2;
}

function context($num1, $num2, $fun)
{
    return $fun($num1, $num2);
}
echo context($num1, $num2, add);                            //这里我直接传add这个function 下游就不用去判断了  直接执行就行了

//补充:上网查了好多(都是互相套,或者拽一些套词,写个demo那么老长 看着也费劲),可能理解的还是不对,这个用对象实现大概也是这么个意思  还是觉得在脱裤子放屁
?>

 

6.装饰器模式

  说明:对一个类的功能进行修改或者添加

  作用:为了应对更多的场景,需要对类的功能进行新增和修改,其实我们也可以采用继承的方式,但假如很多类(继承自同一个接口)都要统一添加和修改一个功能,不是要写很多个子类吗 并且随着扩展功能的增多,子类会很膨胀

  实现:

php
//c1 c2是两个被装饰的类
class C1
{
    function get()
    {
        return 100;
    }
}

class C2
{
    function get()
    {
        return 200;
    }
}

//这个是装饰器
class Decorator
{
    private $obj;
    public function __construct($obj) 
    {
        $this->obj = $obj;
    }
    function get()
    {
        $res = $this->obj->get();
        return $res / 10;
    }
    
    function newGet()
    {
        $res = $this->obj->get();
        return $res + 1;
    }
}
//测试
$obj1 = new Decorator(new C1());
$obj2 = new Decorator(new C2());
echo $obj1->get();
echo $obj1->newGet();
echo $obj2->get();
echo $obj2->newGet();

?>

  补充:看起来是不是和适配器很像,个人总结的两个不同点(1)适配器是为了适配新的环境,入参和调用方式都有可能改变,比如我新增一个type参数,适配器就要为这个做一个拓展。但装饰器不会,调用方式要保证和之前相同,只是为了在之前功能基础上‘装饰’的更漂亮。(2)从定义上看装饰器不仅包括修改,还包括新增

你可能感兴趣的:(php-设计模式)