设计模式

来源:互联网 发布:盛世投资 知乎 编辑:程序博客网 时间:2024/05/29 02:48

SPL常用的数据结构类

1、栈-特点(先进后出)

入栈:

    $stack = new SplStack();    $stack->push("data1\n");    $stack->push("data2\n");

出栈:

    echo $stack->pop();    echo $stack->pop();

结果:

    data2    data1

2、队列(先进先出)

入队:

        $queue = new SplQueue();        $queue->enqueue("data1\n");

出队:

        echo $queue->dequeue();        echo $queue->dequeue(); 

结果:

        data1        data2

3、堆:最小堆使用,直接插入

存入:

    $heap = new SplMinHeap();     $heap->insert("data1\n");    $heap->insert("data2\n");

提取:

    echo $heap->extract();    echo $heap->extract();

结果:

    data1    data2

4、固定长度数组

特点:无论下标是否有值 都分配内存空间保留位置

    $array = new SplFixedArray(10); //输入长度值    $array[0] = 123;    $array[9] = 234;    var_dump($array);

PSR-0规范:

1.命名空间必须与绝对路径一致
2.类名首字母必须大写
3.除入口文件外,其他“.php”必须只有一个类 不能有可执行的代码

设计模式

工厂模式:

1.定义一个专门用来实例化其它对象的类。就是在一个类中封装一些new其他对象的方法,然后返回对象,这样在需要调用某个类的时候,我们就不需要去使用new关键字实例化这个类,而是通过我们的工厂类调用某个方法得到类的实例

2.好处:一旦发生变更,只需要在工厂类里面修改即可,而不用一个一个的去修改

eg:

    <?php        //定义一个工厂类        class Factory{            static function createDatabase(){                $db = new Database();                return $db;            }        }        //在要实例化对象时只要调用工厂类的方法即可        <?php            $db = IMooc\Factory::createDatabase();

单例模式:

1.避免重复实例化一个对象,造成资源浪费

2.步骤:

<1> 构造方法私有化

<2> 声明非公开的成员属性,用于判断类是否被实例化

<3> 声明静态的公有方法,来实例化对象并返回

eg:
    <?php        class Singleton{           //私有化内部实例化的对象            private static $instance = null; //私有化构造方法,禁止外部实例化对象            private function __construct()            {            }            //私有化__clone,防止对象被克隆            private function __clone(){}            // 公有静态实例方法            public static function getInstance()                //如果没有被实例化过,则实例化                if(self::$instance == null){                    //内部实例化对象                    self::$instance = new self();                    //返回                    return self::$instance;        }      }      //使用时调用共有方法实例化,不会多次实例化造成资源浪费      <?php        $db = Database::getInstance();

注册器模式:

1. 已经创建好对象后,下次使用直接取,将一些对象注册到全局树上面,可以用来在任何地方被访问

2. 一般只提供一个set 和 unset 两种方法,需要一个静态的非公开属性和一个取得静态属性的静态方法

3.

<1> set():将对象隐射到全局树上,<2> _unset():从树上移除。<3> get():获取注册到树上的对象。<4> 在框架初始化的时候,会做注册器的初始化操作,然后可以在任何地方去访问注册器的方法。
    eg:        //注册器模式        <?php            class Register{                protected static $objects;                static function set($alias,$object){                    self::$objects[$alias] = $object;                }                static function get($name){                    return self::$objects[$name];                }                function _unset($alias){                    unset(self::$objects[$alias]);                }            }        //在工厂模式下可以这样写        <?php            class Factory{                static function createDatabase(){                    $db =Database::getInstance();                    //调用注册器注册到全局树                    Register::set('db1', $db);                    return $db;                }            }        //调用时        <?php            $db1 = \IMooc\Register::get('db1');

适配器模式

======有待进一步研究==

1. 适配器模式,可以将截然不同的函数接口封装成统一的API

2. 实际应用举例,PHP数据库操作有mysql,mysqli,pdo三种,可以用适配器模式统一成一致。类似场景还有cache适配,将memcache,redis,file,apc等不同的缓存函数,统一成一致


策略模式:

======有待进一步研究==

1. 策略模式,将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式

2. 定义一个策略接口文件,定义策略接口,声明策略

3. 如果上下文环境发生变化,只需要许改策略即可

4.定义具体类,实现策略接口,重写策略方法,

5. 分支逻辑if else,新增一个逻辑以后需要修改每一个if else的地方。使用策略模式以后,只需要增加一个策略类。

6.实现了硬编码到解耦

7.策略模式可以实现IOC、依赖倒置、控制反转。

8. page类依赖于MaleUserStratey这个类,但不需要在page类中实现MaleUserStratey,只有再使用时才绑定,这样以后更方便的替换修改MaleUserStratey类,实现了两个类的解耦,这就是策略模式的依赖倒置
eg:

        UserStrategy.php     策略的接口文件:约定策略的所有行为。        FemaleUserStrategy.php 实现接口的所有方法(不同的策略)        MaleUserStrategy.php实现接口的所有方法(不同的策略)

接口

      <?php        interface Userstrategy{            function showAD();            function showCategory();         }

两个实现不同策略的类

        <?php            class FemaleUserstrategy implements Userstrategy{                function showAD(){                    echo "2015新女装";                }                function showCategory(){                    echo "女装";                }            }        <?php            class MaleUserstrategy implements Userstrategy{                function showAD(){                    echo "2015新男装";                }                function showCategory(){                    echo "男装";                }            }

index文件:

    <?php        class Page{            protected $strategy;            function index(){                echo "AD:";                $this->strategy->showAD();                echo "<br>";                echo "Category:";                $this->strategy->showCategory();                echo "<br>";            }            function setStrategy(IMooc\Userstrategy $strategy){                $this->strategy = $strategy;            }        }

具体实现

        <?php            $page = new Page;            //实现不同的策略            if(isset($_GET['female'])){                $strategy = new \IMooc\FemaleUserstrategy();            }else{                $strategy = new \IMooc\MaleUserstrategy();            }            $page->setStrategy($strategy);            $page->index();

数据对象映射模式

======有待进一步研究==

1. 数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作,比我们在代码中new一个对象,那么使用该模式就可以将对对象的一些操作,比如说我们设置的一些属性,它就会自动保存到数据库,跟数据库中表的一条记录对应起来

2. 实例,在代码中实现数据对象映射模式,我们将写一个ORM类,将复杂的SQL语句映射成对象属性的操作。结合使用数据对象映射模式,工厂模式,注册模式


对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping)

1. 一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

2. 从效果上说,它其实是创建了一个可在编程语言里使用的–“虚拟对象数据库”。

3. 面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。简单的说:ORM相当于中继数据


观察者模式

好处: 在实际项目跨团队多人合作开发中,碰到多事件、多逻辑这种操作的时候,运用观察者模式能够有利于代码的维护!

======有待进一步研究==

1. 观察者模式(Observer),当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新。

2. 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件主体的代码。

3. 观察者模式实现了低耦合,非侵入式的通知与更新机制。

步骤:

<1> 观察者模式是首先定义一个接口,接口空方法做规范。

event.php:

    <?php        namespace IMooc;        interface Observer{            function update($event_info = null);        }

<2> 第二部写一个抽象类,抽象类定义了方法吊用接口的方法。
EventGenerator.php:

    <?php        abstract class EventGenerator{            private $obserers = array();            function addObsever(Observer $observer){            $this->obserers[] = $observer;            }            function ontify(){            foreach ($this->obserers as $observer){                $observer->update();            }            }        }

<3> 写一个子类继承抽象类,然后写个新方法吊用抽象类里面吊用接口的方法。

event.php

    <?php        namespace IMooc;        class Event extends EventGenerator{            function trigger(){            echo "Event <br>";            $this->ontify();            }        }

<4> 最后写观察者实现接口的方法。

Observer1.php

    <?php        class Observer1 implements Observer{            function update($event_info = null){            echo "逻辑1";            }        }

Observer2.php

    <?php        class Observer1 implements Observer{            function update($event_info = null){            echo "逻辑2";            }        }

原型模式

======有待进一步研究==

1. 原型模式与工厂模式作用类似,都是用来创建对象

2. 与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象,以减少new时的开销,这样就免去了类创建时重复的初始化操作,

3. 原型模式适用于大对象的创建,创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可


装饰器模式

======有待进一步研究==

1. 装饰器模式(Decorator),可以动态地添加修改类的功能

2. 一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法

3. 使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性

实现

<1> 写一个装饰器接口

DrawDecorator.php:

    <?php        namespace IMooc;        interface DrawDecorator        {            function beforeDraw();            function afterDraw();        }

<2> 在类中调用接口

Canvas.php:

    <?php        namespace IMooc;            class Canvas        {            //存装饰接口的属性            protected $decorators = array();            //接收并添加装饰接口            function addDecorator(DrawDecorator $decorator)            {                $this->decorators[] = $decorator;            }            //调用装饰器接口            function beforeDraw()            {                foreach($this->decorators as $decorator)                {                    $decorator->beforeDraw();                }            }            //调用装饰器接口            function afterDraw()            {                 //反转是因为before和after都存在的情况下需要一一对应                $decorators = array_reverse($this->decorators);                //遍历因为可能会有多个装饰器                foreach($decorators as $decorator)                {                    $decorator->afterDraw();                }            }            //要修改功能的方法                    function draw()            {                //可以在任何地方实现接口进行修改                //调用方法实现接口                $this->beforeDraw();                foreach($this->data as $line)                {                    foreach($line as $char)                    {                        echo $char;                    }                    echo "<br />\n";                }                //调用方法实现接口                $this->afterDraw();            }        }

3.声明装饰器类实现装饰器接口方法

ColorDrawDecorator.php:

    <?php        namespace IMooc;        class ColorDrawDecorator implements DrawDecorator        {            protected $color;            function __construct($color = 'red')            {                $this->color = $color;            }            function beforeDraw()            {                echo "<div style='color: {$this->color};'>";            }            function afterDraw()            {                echo "</div>";            }        }    ```**SizeDrawDecorator.php**    ```    <?php        namespace IMooc;        class SizeDrawDecorator implements DrawDecorator        {            protected $size;            function __construct($size = '14px')            {                $this->size = $size;            }            function beforeDraw()            {                echo "<div style='font-size: {$this->size};'>";            }            function afterDraw()            {                echo "</div>";            }        }

4. 在使用对象时调用不同的装饰器方法即可实现修改原对象方法功能

    <?php        $canvas1 = new IMooc\Canvas();        $canvas1 -> addDecorator(new \INooc\ColorDrawDecorator('green'));        $canvas1 -> addDecorator(new \IMooc\SizeDrawDecorator('10px'));        $canvas1 -> draw();

迭代器模式

======有待进一步研究==

1. 迭代器模式,在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素。

2. 相比传统的编程模式,迭代器模式可以隐藏遍历元素的所需操作。

实现

1. 实现Iterator接口

    <?php        class AllUser implements Iterator{        }

2. 必须实现Iterator的五个接口

    class AllUser implements Iterator{        function current(){            //返回当前元素        }        function key(){            //返回当前元素的键        }        function next(){            //移动到下一个元素        }        function rewind(){            //返回到迭代器的第一个u        }        function valid(){            //检查当前位置是否有效        }    }3. 调用    $users = new \IMooc\AllUser();    foreach($users as $user){        var_dump($user->name);    }

代理模式

======有待进一步研究==

1. 在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派代理对象,隐藏实体的具体实现细节;

2.proxy还可以与业务代码分离,部署到另外的服务器。业务代码中通过RPC来委派任务

实现(只是举例):

1. 定义一个接口

    <?php        namespace IMooc;        interface IUserProxy        {            function getUserName($id);            function setUserName($id, $name);        }

2. 类中实现接口的方法

    <?php    namespace IMooc;    class Proxy implements IUserProxy    {        function getUserName($id)        {            //创建不同的数据库对象以实现读数据库读写分离            $db = Factory::getDatabase('slave');            $db->query("select name from user where id =$id limit 1");        }        function setUserName($id, $name)        {            $db = Factory::getDatabase('master');            $db->query("update user set name = $name where id =$id limit 1");        }    }

3.调用同一个实现对不同服务器数据库的操作

    <?php        $proxy = new \IMooc\Proxy();        $proxy->getUserName($id);        $proxy->getUserName($id,$proxy);



面向对象编程

基本原则:

1,单一职责:一个类,只需要做好一件事情。2,开放封闭:一个类,应该是可扩展的,而不可修改的。3,依赖倒置:一个类,不应该强依赖另外一个类。每个类对于另外一个类都是可扩展的。(依赖注入)4,配置化:尽可能地使用配置,而不是硬编码5,面向接口编程:只需要关心接口,而不需要关心代码具体实现

MVC

模型--视图--控制器,一种C/S或者B/S软件工程的组织方式
  1. 模型(Model):数据和存储的封装

  2. 视图(View):展现层的封装,如Web系统中的模板文件

  3. 控制器(Controller):逻辑层的封装