zoukankan      html  css  js  c++  java
  • PHP常用设计模式

    一:单例模式

    什么是单例模式?

    只有一个实例。作为对象的创建模式,单例模式确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。

    单例模式的要点:

    1:某个类只能有一个实例。

    2:它必须自行创建这个实例。

    3:它必须自行向整个系统提供这个实例。

    为什么要使用单例模式?

    1:php在数据库应用中,一个应用中会存在大量的数据库应用,在使用面向对象开发时,如果使用单例模式,可以避免大量的new操作消耗资源,还可以减少数据库的连接,这样就不会出现too many connections情况。

    2:如果系统中需要有一个类来全局控制某些配置信息,那么使用单例模式可以很方便的操作。

    3:在一次页面请求中,便于调试,因为所有的代码(例如数据库操作类db)都集中在一个类中,我们可以在类中设计钩子函数,输出日志,从而避免导出var_dump.

    单例模式举例:

    /**
    * 设计模式之单例模式
    * $_instance必须声明为静态的私有变量
    * 构造函数必须声明为私有,防止外部程序new类从而失去单例模式的意义
    * getInstance()方法必须设置为公有的,必须调用此方法以返回实例的一个引用
    * ::操作符只能访问静态变量和静态函数
    * new对象都会消耗内存
    * 使用场景:最常用的地方是数据库连接。
    * 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。
    */
    class man
    {
    //保存例实例在此属性中
    private static $_instance;

    //构造函数声明为private,防止直接创建对象
    private function __construct()
    {
    echo '我被实例化了!';
    }

    //单例方法
    public static function get_instance()
    {
    var_dump(isset(self::$_instance));

    if(!isset(self::$_instance))
    {
    self::$_instance=new self();
    }
    return self::$_instance;
    }

    //阻止用户复制对象实例
    private function __clone()
    {
    trigger_error('Clone is not allow' ,E_USER_ERROR);
    }

    function test()
    {
    echo("test");

    }
    }

    // 这个写法会出错,因为构造方法被声明为private
    //$test = new man;

    // 下面将得到Example类的单例对象
    $test = man::get_instance();
    $test = man::get_instance();
    $test->test();

    // 复制对象将导致一个E_USER_ERROR.
    //$test_clone = clone $test;

    二:工厂模式

    什么是工厂模式?

    工厂模式就是专门负责将大量有共同接口(或者共同抽象父类)的类实例化,而且不必事先知道每次是要实例化哪一个类的模式。他定义一个用于创建对象的接口,由子类决定实例化哪个类。

    工厂模式的要点:

    1:抽象基类:类中定义抽象的方法,用于在子类中实现

    2:继承自抽象基类的子类,实现基类的抽象方法

    3:工厂类:用于实例化所有相对应的子类

    /**
    *
    * 定义个抽象的类,让子类去继承实现它
    *
    */
    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;

    优点:
    工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
    缺点:
    由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
    当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
    这些缺点在工厂方法模式中得到了一定的克服。
    使用场景:
    工厂类负责创建的对象比较少;
    客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
    由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

  • 相关阅读:
    1032. Sharing (25)
    1031. Hello World for U (20)
    1030. Travel Plan (30)
    1029. Median (25)
    1028. List Sorting (25)
    1026. Table Tennis (30)
    win10 tortoiseSVN文件夹及文件图标不显示解决方法
    qrcode.react和jquery.qrcode生成二维码
    js来获取所有屏幕适配的总结
    handsontable整理
  • 原文地址:https://www.cnblogs.com/hupengyin/p/6278188.html
Copyright © 2011-2022 走看看