简单的设计模式

设计模式

单例模式

这个类只能创建一个对象。

php的应用主要在于数据库应用,一个应用中会存在大量的数据库操作,使用单例模式,可以避免大量的 new 操作消耗的资源

步骤

  1. 构造函数需要标记为private

  2. 保存类实例的静态成员变量

  3. 获取实例的公共的静态方法

    class Single {
        private $name;//声明一个私有的实例变量
        private function __construct(){//声明私有构造方法为了防止外部代码使用new来创建对象。
        }
        static public $instance;//声明一个静态变量(保存在类中唯一的一个实例)
        static public function getinstance(){//声明一个getinstance()静态方法,用于检测是否有实例对象
            if(!self::$instance) self::$instance = new self();
            return self::$instance;
        }
        public function setname($n){ $this->name = $n; }
        public function getname(){ return $this->name; }
    }
    

简单工厂、标准工厂

接口中定义一些方法

实现接口的类实现这些方法

工厂类:用以实例化对象

优点:为系统结构提供了灵活的动态扩展机制。方便维护

     /**
      * 操作类
      * 因为包含有抽象方法,所以类必须声明为抽象类
      */
     abstract class Operation{
         //抽象方法不能包含函数体
         abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
     }
     /**
      * 加法类
      */
     class OperationAdd extends Operation {
         public function getValue($num1,$num2){
             return $num1+$num2;
         }
     }
     /**
      * 减法类
      */
     class OperationSub extends Operation {
         public function getValue($num1,$num2){
             return $num1-$num2;
         }
     }
     /**
      * 乘法类
      */
     class OperationMul extends Operation {
         public function getValue($num1,$num2){
             return $num1*$num2;
         }
     }
     /**
      * 除法类
      */
     class OperationDiv extends Operation {
         public function getValue($num1,$num2){
             try {
                 if ($num2==0){
                     throw new Exception("除数不能为0");
                 }else {
                     return $num1/$num2;
                 }
             }catch (Exception $e){
                 echo "错误信息:".$e->getMessage();
             }
         }
     }

工厂方法

工厂方法模式核心是工厂类不再负责所有对象的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,它仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节

    /**
     * 工程类,主要用来创建对象
     * 功能:根据输入的运算符号,工厂就能实例化出合适的对象
     *
     */
    class Factory{
        public static function createObj($operate){
            switch ($operate){
                case '+':
                    return new OperationAdd();
                    break;
                case '-':
                    return new OperationSub();
                    break;
                case '*':
                    return new OperationSub();
                    break;
                case '/':
                    return new OperationDiv();
                    break;
            }
        }
    }
    $test=Factory::createObj('/');
    $result=$test->getValue(23,0);
    echo $result;

观察者

它是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式提供了避免组件之间紧密耦合的另一种方法

涉及到两个类:

一个是被观察者

  1. 添加观察者
  2. 删除观察者
  3. 发送通知

一个是观察者

  1. 做出反应即可

    在php中:用户注册(收到邮件,收到短信,或者收到其他信息)

     //先定义一个被观察者的接口,这个接口要实现注册观察者,删除观察者和通知的功能。
     interface Observables
     {
        public function attach(observer $ob);
        public function detach(observer $ob);
        public function notify();
     }
    
     class Saler implements Observables
     {
        protected $obs = array();       //把观察者保存在这里
        protected $range = 0;
    
        public function attach(Observer $ob)
        {
            $this->obs[] = $ob;
        }
    
        public function detach(Observer $ob)
        {
            foreach($this->obs as $o)
            {
                if($o != $ob)
                    $this->obs[] = $o;
            }
        }
    
        public function notify()
        {
            foreach($this->obs as $o)
            {
                $o->doActor($this);
            }
        }
    
        public function increPrice($range)
        {
            $this->range = $range;
        }
    
        public function getAddRange()
        {
            return $this->range;
        }
     }
    
    //定义一个观察者的接口,这个接口要有一个在被通知的时候都要实现的方法
    interface Observer
    {
       public function doActor(Observables $obv);
    }

   //为了容易阅读,我在这里增加了一层,定义了一个买家, 之后会有Poor和Rich两种不同的类型继承这个类,用以表示不同类型的买家 
    abstract class Buyer implements Observer
    {
    }
    
    class PoorBuyer extends Buyer
    {
        //PoorBurer的做法
       public function doActor(observables $obv)
       {
           if($obv->getAddRange() > 10)
               echo  '不买了.
'; else echo '还行,买一点吧.
'; } } class RichBuyer extends Buyer { //RichBuyer的做法 public function doActor(observables $obv) { echo '你再涨我也不怕,咱不差钱.
'; } } $saler = new Saler(); //小贩(被观察者) $saler->attach(new PoorBuyer()); //注册一个低收入的消费者(观察者) $saler->attach(new RichBuyer()); //注册一个高收入的消费者(观察者) $saler->notify(); //通知 $saler->increPrice(2); //涨价 $saler->notify(); //通知

官方接口

​ SplSubject

​ attach 添加观察者

​ detach 删除观察者

​ notify 通知

​ SplOberser

​ update 做出响应

SplSubject代表着被观察的对象,其结构:

interface SplSubject{
//添加(注册)一个观察者
public function attach(SplObserver $observer);
//删除一个观察者
public function detach(SplObserver $observer);
//当状态发生改变时,通知所有观察者
    public function notify();
}

SplObserver 代表着充当观察者的对象,其结构:

interface SplObserver{
  //在目标发生改变时接收目标发送的通知;当关注的目标调用其notify()时被调用 
  public function update(SplSubject $subject);
}

具体实现

class MyObserver1 implements SplObserver
{
    public function update(SplSubject $subject)
    {
        echo "MyObserver1 updated\n";
    }
}

class MyObserver2 implements SplObserver
{
    public function update(SplSubject $subject)
    {
        echo "MyObserver2 updated\n";
    }
}

class MySubject implements SplSubject
{
    private $_observers;
    private $_name;

    public function __construct($name)
    {
        $this->_observers = new SplObjectStorage();
        $this->_name = $name;
    }

    public function attach(SplObserver $observer)
    {
        $this->_observers->attach($observer);
    }

    public function detach(SplObserver $observer)
    {
        $this->_observers->detach($observer);
    }

    public function notify()
    {
        foreach ($this->_observers as $observer) {
            $observer->update($this);
        }
    }

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

测试用例

class testDriver
{
    public function run()
    {
        $observer1 = new MyObserver1();
        $observer2 = new MyObserver2();
        $subject = new MySubject("test");
        $subject->attach($observer1);
        $subject->attach($observer2);
        $subject->notify();
    }
}

$test = new testDriver();
$test->run();

适配器

可将一个类的接口转换成客户希望的另外一个接口,使得原本不兼容的接口能够一起工作。通俗的理解就是将不同接口适配成统一的接口

  1. 你想使用一个已经存在的类,而它的接口不符合你的需求
  1. 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
  1. 你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口(仅限于对象适配器)
简单的设计模式_第1张图片
img
//目标角色  
interface Target {  
    public function simpleMethod1();  
    public function simpleMethod2();  
}  
  
//源角色  
class Adaptee {  
    public function simpleMethod1(){  
        echo 'Adapter simpleMethod1'."
"; } } //类适配器角色 class Adapter implements Target { private $adaptee; function __construct(Adaptee $adaptee) { $this->adaptee = $adaptee; } //委派调用Adaptee的sampleMethod1方法 public function simpleMethod1(){ echo $this->adaptee->simpleMethod1(); } public function simpleMethod2(){ echo 'Adapter simpleMethod2'."
"; } } //客户端 class Client { public static function main() { $adaptee = new Adaptee(); $adapter = new Adapter($adaptee); $adapter->simpleMethod1(); $adapter->simpleMethod2(); } } Client::main();

策略模式

策略模式是对象的行为模式,用意是对一组算法的封装。动态的选择需要的算法并使用。

(1)多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。

(2)需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。

(3)对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

(4)客户端必须知道所有的策略类,并自行决定使用哪一个策略类,策略模式只适用于客户端知道所有的算法或行为的情况。

(5)策略模式造成很多的策略类,每个具体策略类都会产生一个新类。

优点:

​ 1、策略模式提供了管理相关的算法族的办法

​ 2、算法封闭在独立的Strategy类中使得你可以独立于其Context改变它

​ 3、使用策略模式可以避免使用多重条件转移语句

    abstract class baseAgent { //抽象策略类
        abstract function PrintPage();
    }
    //用于客户端是IE时调用的类(环境角色)
    class ieAgent extends baseAgent {
        function PrintPage() {
            return 'IE';
        }
    }
    //用于客户端不是IE时调用的类(环境角色)
    class otherAgent extends baseAgent {
        function PrintPage() {
            return 'not IE';
        }
    }
    class Browser { //具体策略角色
        public function call($object) {
            return $object->PrintPage ();
        }
    }
    $bro = new Browser ();
    echo $bro->call ( new ieAgent () );

门面模式

优点

​ 1. 它对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便

​ 2. 实现了子系统与客户之间的松耦合关系

​ 3. 如果应用需要,它并不限制它们使用子系统类。因此可以在系统易用性与能用性之间加以选择

适用场景

​ 1. 为一些复杂的子系统提供一组接口

​ 2. 提高子系统的独立性

​ 3.在层次化结构中,可以使用门面模式定义系统的每一层的接口

/**  
 (1)外观模式(Facade)也叫门面模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
     为一些复杂的子系统提供一组接口

 (2)主要角色
门面(Facade)角色
•   此角色将被客户端调用
•   知道哪些子系统负责处理请求
•   将用户的请求指派给适当的子系统
子系统(subsystem)角色
•   实现子系统的功能
•   处理由Facade对象指派的任务
•   没有Facade的相关信息,可以被客户端直接调用
•   可以同时有一个或多个子系统,每个子系统都不是一个单独的类,而一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调

(3)使用情况 :

    首先,在设计初期阶段,应该要有意识将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、
业务逻辑层和表示层的层与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合度大大降低。
    其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,
但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。
    第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。
此时,用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰的简单接口,
让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。”

(4) 具体事例 
比如我关机,整个过程包括关闭显示器,关闭pc机器,关闭电源 ,关机的按钮就是门面的角色,其他为子系统
*/

// 门面抽象接口 
interface Facade{   
    public function turnOn() ;
    public function turnOff() ;
}


// (1) 关闭显示器

class PcLight {
    public function turnOn() {}
    public function turnOff() {
        echo 'turn off PcLight 
' ; } } //(2) pc 机器 class Pcmachine { public function turnOn() {} public function turnOff() { echo 'turn off PcMathion
' ; } } // (3) 关闭电源 class Power { public function turnOn() {} public function turnOff() { echo 'turn off Power
' ; } } // 关机的门面角色 class PcFacade implements Facade{ private $PcLight ; private $Pcmachine ; private $Power ; public function __construct(){ $this->PcLight = new PcLight(); $this->Pcmachine = new Pcmachine(); $this->Power = new Power(); } // 门面角色的应用 public function turnOff() { $this->PcLight ->turnOff(); $this->Pcmachine ->turnOff(); $this->Power ->turnOff(); } public function turnOn() {} } // 应用 $button = new PcFacade(); $button ->turnOff(); /* 其实门面模式就是把几个子系统(实例或者类.统一一个统一的接口进行执行,客户端不用关注子系统,只用门面即可 )

DI(Dependency Injection)依赖注入 (Ioc反转控制)

依赖注入

//当一个方法调用的时候,需要依赖于其他对象,才能个完成功能。那么我们就叫这个为依赖注入,也叫翻转控制。
class Son
{
    public function cry(Father $father)
    {
        echo '你看我很不要脸的哭了。
'; $father->baobao(); } } class Father { public function baobao() { echo '很帅很帅的爸爸来抱抱。'; } } class Mother { public function baobao() { echo '很美很美的妈妈来抱抱
'; } } $son = new Son(); $father = new Father(); $son->cry($father);

反射

ReflectionClass 反射类对象

ReflectionMethod 反射方法对象

ReflectionParameters 反射参数对象

class UserController
{
    public function index(UserModel $user, ArticleModel $article, Session $session)
    {
        var_dump($user->profile());
        var_dump($article->info());
        var_dump($session->get());
    }
}
class UserModel
{
    public function profile()
    {
        return '查出了用户的属性。';
    }
}
class ArticleModel
{
    public function info()
    {
        return '查出来了文章的详情。';
    }
}
class Session
{
    public function get()
    {
        return '获取了一个Session';
    }
}
/*call_user_func_array(array(new UserController(),'index'),array(new UserModel(),new ArticleModel()));*/
class App
{
    static public function run($instance, $method)
    {
        $r = new ReflectionMethod($instance,$method);
        $parameters = $r->getParameters();
        $paramObj = [];
        foreach ($parameters as $param) {
            $class = $param->getClass();
            $paramObj[] = new $class->name();
        }
        call_user_func_array(array($instance,$method),$paramObj);
        var_dump($paramObj);
    }
}

class Container
{
    static public $things = [];
    //在容器里取东西
    static public function bind($name, Closure $method)
    {
        if (!isset(self::$things[$name])) {
            self::$things[$name] = $method;
        }
    }

    //在容器中放东西
    static public function make($name)
    {
        if(isset(self::$things[$name])){
            $func = self::$things[$name];
            return $func();
        }
    }
}
Container::bind('UserModel',function(){
    return new UserModel();
});
Container::bind('ArticleModel',function(){
    return new ArticleModel();
});
Container::bind('Session',function(){
    return new Session();
});
App::run(new UserController(),'index');

MVC

mvc概念

​ model view controller

psr规范

​ psr1:基础编程规范

​ psr2:编码风格规范

​ psr3:日志接口规范

​ psr4:自动加载规范

单一入口(简单路由)

简单模式   index.php?m=index&a=index

pathinfo  index.php/index/index

spl_autoload_register

__autoload($className)
    

框架目录架构

app

​ model

​ UserModel.php

view

​ user

​ login.html

​ register.html

​ index

​ index.html

​ about.html

controller

​ Controller.php

​ UserController.php

​ IndexController.php

config

​ config.php

vendor

​ lib

​ Model.php

​ Page.php

​ Tpl.php

public

​ css

​ js

​ fonts

​ editor

cache

​ 缓存

你可能感兴趣的:(简单的设计模式)