浅谈PHP设计模式

  • 1.单例模式

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

单例模式的要点有三个:

  1. 只能有一个实例,必须拥有一个构造函数,并且必须被标记为private
  2. 必须自行创建这个实例,拥有一个保存类的实例的静态成员变量
  3. 必须给其他对象提供这一实例,拥有一个访问这个实例的公共的静态方法

单例类不能在其它类中直接实例化,只能被其自身实例化。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。在PHP中,为防止对单例类对象的克隆来打破单例类的上述实现形式,通常还为基提供一个空的私有__clone()方法。

为什么要使用PHP单例模式

  1.  php的应用主要在于数据库应用, 一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时, 如果使用单例模式, 则可以避免大量的new 操作消耗的资源,还可以减少数据库连接这样就不容易出现 too many connections情况。
  2.  如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 
  3. 在一次请求中, 便于进行调试, 因为所有的代码(如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处查找问题。
  4. global全局变量,也起到单例模式的作用,但在OOP中,我们建议拒绝这种编码。因为global存在安全隐患(全局变量不受保护的本质)。全局变量是面向对象程序员遇到的引发BUG的主要原因之一。这是因为全局变量将类捆绑于特定的环境,破坏了封装。如果新的应用程序无法保证一开始就定义了相同的全局变量,那么一个依赖于全局变量的类就无法从一个应用程序中提取出来并应用到新应用程序中。确切的讲,单例模式恰恰是对全局变量的一种改进,避免那些存储唯一实例的全局变量污染命名空间。你无法用错误类型的数据覆写一个单例。这种保护在不支持命名空间的PHP版本里尤其重要。因为在PHP中命名冲突会在编译时被捕获,并使脚本停止运行。

单例模式实现代码如下

/**
  * 设计模式之单例模式
  * $_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. 是对全局变量的一种改进

缺点:

  1. 难于调试
  2. 隐藏的依赖关系
  3. 无法用错误类型的数据覆写一个单例

 

  • 2.工厂模式

  1.  工厂模式就是一种类,是指包含一个专门用来创建其他对象的方法的类。工厂类在多态性编程实践中是至关重要的,它允许动态的替换类,修改配置,通常会使应用程序更加灵活,熟练掌握工厂模式高级PHP开发人员是很重要的。
  2.  工厂模式通常用来返回符合类似接口的不同的类,工厂的一种常见用法就是创建多态的提供者,从而允许我们基于应用程序逻辑或者配置设置来决定应实例化哪一个类,例如,可以使用这样的提供者来扩展一个类,而不需要重构应用程序的其他部分,从而使用新的扩展后的名称 。
  3. 通常,工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,工厂方法可以任意命名,这个静态还可以接受任意数据的参数,必须返回一个对象。具有为您创建对象的某些方法,这样就可以使用工厂类创建对象,工厂模式在于可以根据输入参数或者应用程序配置的不同来创建一种专门用来实现化并返回其它类的实例的类,而不直接使用new,这样如果想更改创建的对象类型,只需更改该工厂即可。

简单的说,PHP工厂模式就是用一个工厂方法来替换掉直接new对象的操作,就是为方便扩展,方便使用,在新增实现基类中的类中方法时候,那么在工厂类中无需修改,传入参数可以直接使用,具体就是跳过工厂类修改,直接使用工厂类输出想要的结果。

  • ①抽象基类:类中定义抽象一些方法,用以在子类中实现
  • ②继承自抽象基类的子类:实现基类中的抽象方法
  • ③工厂类:用以实例化所有相对应的子类

6e4d07cf6f9e11a46ca04ed594cddaa0f43.jpg

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

通过采用面向对象的继承特性,我们可以很容易就能对原有程序进行扩展,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’等,以还可以避免加载没有必要的代码。

如果我们现在需要增加一个求余的或者除法运算的类,会非常的简单。我们只需要另外写一个类(该类继承虚拟基类),在类中完成相应的功能(比如:求乘方的运算),而且大大的降低了耦合度,方便日后的维护及扩展 。

/**
  * 求余类(remainder)
  *
  */
 class OperationRem extends Operation {
     public function getValue($num1,$num2){
         return $num1%$num12;
     }
 }

接下来就是如何让程序根据用户输入的操作符实例化相应的对象了。解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂

/**
  * 工程类,主要用来创建对象
  * 功能:根据输入的运算符号,工厂就能实例化出合适的对象
  *
  */
  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;

 

转载于:https://my.oschina.net/u/3432745/blog/3018917

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值