设计模式

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:

    
        //定义一个工厂类
        class Factory{
            static function createDatabase(){
                $db = new Database();
                return $db;
            }
        }

        //在要实例化对象时只要调用工厂类的方法即可
        
            $db = IMooc\Factory::createDatabase();

单例模式:

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

2.步骤:

<1> 构造方法私有化

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

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

eg:
    
        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;
        }
      }

      //使用时调用共有方法实例化,不会多次实例化造成资源浪费
      
        $db = Database::getInstance();

注册器模式:

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

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

3.

<1> set():将对象隐射到全局树上,

<2> _unset():从树上移除。

<3> get():获取注册到树上的对象。

<4> 在框架初始化的时候,会做注册器的初始化操作,然后可以在任何地方去访问注册器的方法。
    eg:
        //注册器模式
        
            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]);
                }
            }

        //在工厂模式下可以这样写
        
            class Factory{
                static function createDatabase(){
                    $db =Database::getInstance();
                    //调用注册器注册到全局树
                    Register::set('db1', $db);
                    return $db;
                }
            }

        //调用时
        
            $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实现接口的所有方法(不同的策略)

接口

      
        interface Userstrategy{
            function showAD();
            function showCategory(); 
        }

两个实现不同策略的类

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

index文件:

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

具体实现

        
            $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:

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

<2> 第二部写一个抽象类,抽象类定义了方法吊用接口的方法。
EventGenerator.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

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

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

Observer1.php

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

Observer2.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:

    
        namespace IMooc;

        interface DrawDecorator
        {
            function beforeDraw();
            function afterDraw();
        }

<2> 在类中调用接口

Canvas.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 "
\n"
; } //调用方法实现接口 $this->afterDraw(); } }

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

ColorDrawDecorator.php:

    
        namespace IMooc;

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

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

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

迭代器模式

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

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

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

实现

1. 实现Iterator接口

    

        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. 定义一个接口

    
        namespace IMooc;

        interface IUserProxy
        {
            function getUserName($id);
            function setUserName($id, $name);
        }

2. 类中实现接口的方法

    
    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.调用同一个实现对不同服务器数据库的操作

    $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):逻辑层的封装

你可能感兴趣的:(算法和数据结构,设计模式)