php面向对象:观察者模式示例

 更新时间:2016年11月25日 15:36  点击:2062
观察者模式也是php面向对象中的一个不常用的模式了,下面我们一起来看看php面向对象:观察者模式示例,希望对给各位带来帮助。

意图:

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新【GOF95】

又称为发布-订阅(Publish-Subscribe)模式、模型-视图(Model-View)模式、源-监听(Source-Listener)模式、或从属者(Dependents)模式

结构图:

php面向对象:观察者模式示例

 

主要角色

抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。抽象主题提供了增加和删除观察者对象的接口。

抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。

具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。

具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。

优点和缺点

优点:观察者和主题之间的耦合度较小,支持广播通信。

缺点:由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。

适用场景

当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。

当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。

实现代码

<?php
 
/**
* 观察者模式
 
* @package design pattern
*/
 
/**
* 抽象主题角色
*/
interface Subject {
 
    /**
     * 增加一个新的观察者对象
     * @param Observer $observer
     */
    public function attach(Observer $observer);
 
    /**
     * 删除一个已注册过的观察者对象
     * @param Observer $observer
     */
    public function detach(Observer $observer);
 
    /**
     * 通知所有注册过的观察者对象
     */
    public function notifyObservers();
}
 
/**
* 具体主题角色
*/
class ConcreteSubject implements Subject {
 
    private $_observers;
 
    public function __construct() {
        $this->_observers = array();
    }
 
    /**
     * 增加一个新的观察者对象
     * @param Observer $observer
     */
    public function attach(Observer $observer) {
        return array_push($this->_observers, $observer);
    }
 
    /**
     * 删除一个已注册过的观察者对象
     * @param Observer $observer
     */
    public function detach(Observer $observer) {
        $index = array_search($observer, $this->_observers);
        if ($index === FALSE || ! array_key_exists($index, $this->_observers)) {
            return FALSE;
        }
 
        unset($this->_observers[$index]);
        return TRUE;
    }
 
    /**
     * 通知所有注册过的观察者对象
     */
    public function notifyObservers() {
        if (!is_array($this->_observers)) {
            return FALSE;
        }
 
        foreach ($this->_observers as $observer) {
            $observer->update();
        }
 
        return TRUE;
    }
 
}
 
/**
* 抽象观察者角色
*/
interface Observer {
 
    /**
     * 更新方法
     */
    public function update();
}
 
class ConcreteObserver implements Observer {
 
    /**
     * 观察者的名称
     * @var <type>
     */
    private $_name;
 
    public function __construct($name) {
        $this->_name = $name;
    }
 
    /**
     * 更新方法
     */
    public function update() {
        echo 'Observer', $this->_name, ' has notified.<br />';
    }
 
}
 
   $subject = new ConcreteSubject();
 
        /* 添加第一个观察者 */
        $observer1 = new ConcreteObserver('Martin');
        $subject->attach($observer1);
 
        echo '<br /> The First notify:<br />';
        $subject->notifyObservers();
 
        /* 添加第二个观察者 */
        $observer2 = new ConcreteObserver('phppan');
        $subject->attach($observer2);
 
        echo '<br /> The Second notify:<br />';
        $subject->notifyObservers();
 
        /* 删除第一个观察者 */
        $subject->detach($observer1);
 
        echo '<br /> The Third notify:<br />';
        $subject->notifyObservers();

phpmyadmin是一款mysql图形管理的界面了,我们在此来为各位介绍在phpmyadmin增加mysql用户了,希望本文章可以给各位朋友带来帮助。
前言:phpmyadmin添加非root数据库管理账户安全还是有必要的。通过phpmyadmin可以方便的进行mysql添加删除用户等操作。添加完非root账户后就可以用添加的账户登陆phpmyadmin删除原来的root账户了,对于安全性还是有好处的。

 

第1步:打开phpMyAdmin,点击菜单栏的【用户】按钮,进入用户管理页面。


1.jpg

 

第2步:用户管理页面列出了现有用户信息,点击【添加用户】创建新用户。


2.jpg

 

第3步:输入用户名【User name】。有两个选项:任意用户、使用文本域,它们之间没有明显区别,推荐选择“使用文本域”,然后在文本框中输入用户名,如sky。


3.jpg

 

第4步:输入主机【Host】信息。这里有四个选项:任意主机(%)、本地( localhost)、使用主机表(host)、Use text field(即使用文本域)。
任意主机表示匹配所有主机;本地表示仅限本地主机(默认填写localhost);使用主机指以MySQL数据库中的host表中的数据为准,不需填写任何信息(如果填写则此选项无效);使用文本域表示自行填写主机地址信息。此处选择“本地”选项。


4.jpg

 

第5步:输入密码和Re-type(确认密码)。有两个选项:无密码、使用文本域。此处选择“使用文本域”,可以手动输入密码,也可以点击【生成】按钮,自动生成密码并在最下方文本框中显示。

 

5.jpg

 

第6步:为用户分配权限。权限管理分为两大块:用户数据库和全局权限。
用户数据库包括两个选项:创建与用户同名的数据库并授予所有权限;给以用户名_开通的数据库授予所有权限。可根据需要自行选择。此处两个都未选,仅创建新用户。
全局权限包括四部分:数据、结构、管理和资源限制。可根据需要自行选择。这里我选择了“全选”,全选相当于root的所有权限。当然也可以把管理那个不选,这样账户只是拥有读写等权限而没有整个mysql的管理权限。

 

6.jpg

 

第7步:权限分配好后,点击右下角的【执行】按钮,执行创建新用户操作。老版本的好像还要回到phpMyAdmin的首页,重新加载一下授权,有个选项是Reload privileges点击下就可以了
工厂模式是什么?是不是在工厂做事呢?我相信有一些朋友对于php工厂模式还是有一些不理解,下文整理一些关于工厂模式例子。

简单工厂模式:


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


php面向对象之工厂模式示例 

先看一种代码:

<?php
    class Calc{
        /**
         * 计算结果
         *
         * @param int|float $num1
         * @param int|float $num2
         * @param string $operator
         * @return int|float
         */
        public function calculate($num1,$num2,$operator){
            try {
                $result=0;
                switch ($operator){
                    case '+':
                        $result= $num1+$num2;
                        break;
                    case '-':
                        $result= $num1-$num2;
                        break;
                    case '*':
                        $result= $num1*$num2;
                        break;
                    case '/':
                        if ($num2==0) {
                            throw new Exception("除数不能为0");
                        }
                        $result= $num1/$num2;
                        break;
                }
            return $result;
            }catch (Exception $e){
                echo "您输入有误:".$e->getMessage();
            }
        }
    }
    $test=new Calc();
//    echo $test->calculate(2,3,'+');//打印:5
    echo $test->calculate(5,0,'/');//打印:您输入有误:除数不能为0
?>
 

优点:以上代码使用了面向对象的封装特性,只要有了include这个类,其他页面就可以随便使用了

缺点:无法灵活的扩展和维护
比如:想要增加一个“求余”运算,需要在switch语句块中添加一个分支语句,代码需要再加一个case进行判断

于是产生了以下问题

①需要改动原有的代码块,可能会在为了“添加新功能”而改动原有代码的时候,不小心将原有的代码改错了
②如果要添加的功能很多,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’,或者添加一些程序员专用的计算功能,比如:And, Or, Not, Xor,这样就需要在switch语句中添加N个分支语句。想象下,一个计算功能的函数如果有二三十个case分支语句,代码将超过一屏,不仅令代码的可读性大大降低,关键是,为了添加小功能,还得让其余不相关都参与解释,这令程序的执行效率大大降低。

解决途径:采用OOP的继承和多态思想

 <?php
     /**
      * 操作类
      * 因为包含有抽象方法,所以类必须声明为抽象类
      */
     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();
             }
         }
     }
 ?>
 

 <?php
     /**
      * 操作类
      * 因为包含有抽象方法,所以类必须声明为抽象类
      */
     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();
             }
         }
     }
 ?>
 

这里采用了面向对象的继承特性,首先声明一个虚拟基类,在基类中指定子类务必实现的方法(getValue())

分析:通过采用面向对象的继承特性,我们可以很容易就能对原有程序进行扩展,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’等等。

我们只需要另外写一个类(该类继承虚拟基类),在类中完成相应的功能(比如:求乘方的运算),而且大大的降低了耦合度,方便日后的维护及扩展.

现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?
解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂.

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

我对些的总结就是:根据传递的参数(对象)不同,调用不同的工厂(类)。然后用以实现指定的功能。比较大的好处就是简化了以前函数化编程的switch case,if else之类,进行类的分发,不同的东西调用不同的类。

插入排序是各种排名中一种了,今天小编就为各位介绍插入排序使用php来实现 了,有兴趣的朋友不防进来来看看吧。

排序算法的种类是多种多样,各有各的长处,这几天会一一进行分析。学习应该有一个先后递进的过程,从容易的开始。

先说比较简单的 — 插入排序(由PHP代码实现,这里不讲究效率!)

/**
* 插入排序 -- 比冒泡稍微复杂一点的排序算法 *
*
**/
 
$array = array('5','6','3','1','2','4');
 
/**
   * 插入排序1 -- 使用最暴力的排序
   *
**/
 
function insertSort($array)
    {
       $count = count($array); //先取出一个数据最为比较数据
       for($i=1;$i<$count;$i++)
       {
           $key = $array[$i];
           $j = $i-1;
           while($j>=0 && $array[$j]>$key)
          {
               $array[$j+1] = $array[$j];
               $j = $j-1;
               $array[$j+1] = $key;
            }
           var_dump($array);
      }
   }
 
 insertSort($array);

下面是运行结果:

 

php 插入排序程序代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 嗯,整个算法已经完了!如果你只想要代码的。你事情已经完成了,下面开始讲原理。

插入排序之所以叫插入排序,我们可以形象的理解为:

你摸牌的时候,你手里的牌是有序的,而你从牌堆里摸的牌是随机出现的,你只需跟你手里的牌进行比较排序,就能确定新牌的位置

插入的排序的逻辑可以简单的理解为,从第二个元素前,开始跟第一个元素进行比较,如果比对一个元素小,该元素就插入到第一个元素的前面

如果大,则跟第二个元素进行比较,以此类推。(从效果图中,可以看出来)

再来看看插入排序的时间发杂度:

最优的情况,所有的N-1个元素只需要跟前面的元素比较一次,那么时间复杂度是n-1;
最差的勤快,所有的N-1个元素都需要跟前面的所有元素比较一次,那么时间复杂度是一个等差数列 ((n-1)*(n-2))/2+(n-1);
综上所述:插入排序的时间复杂度应该是位于这两则之间。

空间复杂度: 插入排序是一种线性排序。所有空间复杂度跟参与排序的N有关。

PHPExcel是一个php 操作excel表格的插件了,我们可以使用它来进行数据导入或导入操作,但有时我们需要一些特殊的列名,那么要如何操作。

今天导出Excel的时候,列不是固定的,而且有差不多几十个,横轴由’A’变为了’AA’,给导出时增加了难度,因为要去算列名称,不过换个方式想一下,发现是很有规律的26进制数。 发现秘诀后就好办了,发一个10进制转26进制的方法。

private function numberToStr26($n)
{
    $s = '';
    while ($n > 0) {
        $m = $n % 26;
        if ($m == 0) $m = 26;
        $s = chr($m + 64) . $s;
        $n = ($n - $m) / 26;
    }
    return $s;
}

看张效果图片

 

PHPExcel导出时列过大问题解决办法
[!--infotagslink--]

相关文章

  • php Observer观察者模式之学习笔记

    当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
  • JS实现简单面向对象的颜色选择器实例

    这篇文章主要介绍了JS实现简单面向对象的颜色选择器,以完整实例形式分析了JavaScript基于面向对象实现颜色选择器的具体步骤与实现技巧,需要的朋友可以参考下...2016-04-23
  • 学习JavaScript设计模式之观察者模式

    这篇文章主要为大家介绍了JavaScript设计模式中的观察者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • 浅析从面向对象思维理解Vue组件

    用面向对象的思维去理解Vue组件,可以将所有的事物都抽象为对象,而类或者说是组件,都具有属性和操作。这篇文章主要介绍了尝试用面向对象思维理解Vue组件,需要的朋友可以参考下...2021-07-11
  • 浅谈对c# 面向对象的理解

    这篇文章主要介绍了个人对c# 面向对象的理解,算是一个入门篇吧,给需要的小伙伴参考下,抛砖引玉。...2020-06-25
  • php面向对象之反射功能与用法分析

    这篇文章主要介绍了php面向对象之反射功能与用法,结合实例形式简单分析了php5面向对象反射的概念及具体用法,需要的朋友可以参考下...2017-04-03
  • C#面向对象编程基础概念汇总

    今天小编就为大家分享一篇关于C#面向对象编程基础概念汇总的文章,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...2020-06-25
  • 一起来了解JavaScript面向对象

    本篇文章主要介绍了Javascript的面向对象,小编觉得这篇文章内容很不错,需要的朋友可以看下,希望能够给你带来帮助...2021-09-27
  • PHP面向对象开发之类中接口的应用(interface、implements)

    php类中接口的应用关键字是interface、implements了,接口是一种成员属性全部为抽象或常量的特殊抽象类,下面我们看几个实例。 类中接口的应用 1.关键字:interface...2016-11-25
  • C#中面向对象编程机制之继承学习笔记

    这篇文章主要介绍了C#中面向对象编程机制之继承学习笔记,本文给出一个简单子实例讲解C#中的继承,并讲解了一些C#继承的知识技巧,需要的朋友可以参考下...2020-06-25
  • PHP的面向对象编程:开发大型PHP项目的方法(三)(转载)

    PHP的面向对象编程:开发大型PHP项目的方法(三) 作者:Luis Argerich 译者:limodou   重载(与覆盖不同)在PHP中不支持。在OOP中,你可以重载一个方法来实现两个或重多的方法...2016-11-25
  • PHP面向对象:使用接口与组合模拟多继承(1/2)

    在php中不支持多重继承,如果我们向使用多个类的方法而实现代码重用有什么办法么?那就是组合。在一个类中去将另外一个类设置成属性。 下面的例子,模拟了多重继承。 view s...2016-11-25
  • Java面向对象基础,类,变量,方法

    这篇文章主要介绍了Java面向对象基础,类,变量,方法,需要的朋友可以参考下...2020-10-03
  • 详解JavaScript基于面向对象之继承

    这篇文章主要介绍了JavaScript基于面向对象之继承...2015-12-14
  • php 面向对象编程之构造方法与析构方法

    大多数类都有一种称为构造函数的特殊方法。当创建一个对象时,它将自动调用构造函 数,也就是使用new 这个关键字来实例化对象的时候自动调用构造方法。 构造函数的声...2016-11-25
  • 详解JS面向对象编程

    这篇文章主要为大家介绍了js面向对象编程,感兴趣的小伙伴们可以参考一下...2016-01-25
  • PHP:我坚决站在面向对象一边

    PHP 语言从诞生起,就具有了很好的面向过程编程的特性。只是在其进化过程中才逐渐加强了面向对象的特性,直到 PHP5.0,也才接近完善。一般来说,PHP 的初学者和...2016-11-25
  • 老生常谈PHP面向对象之命令模式(必看篇)

    下面小编就为大家带来一篇老生常谈PHP面向对象之命令模式(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2017-05-26
  • C#观察者模式(Observer Pattern)实例教程

    这篇文章主要介绍了C#观察者模式(Observer Pattern),主要以一个实例的形式讲述了C#观察者模式的实现过程,详细讲述了接口的定义、通知及动作的实现方法,需要的朋友可以参考下...2020-06-25
  • Python面向对象封装操作案例详解

    这篇文章主要介绍了Python面向对象封装操作,结合具体案例形式详细分析了Python面向对象的封装、扩展等操作技巧与相关注意事项,需要的朋友可以参考下...2020-05-06