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

 更新时间:2016年11月25日 15:36  点击:1375
工厂模式是什么?是不是在工厂做事呢?我相信有一些朋友对于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面向对象:观察者模式示例,希望对给各位带来帮助。

意图:

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新【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();

插入排序是各种排名中一种了,今天小编就为各位介绍插入排序使用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导出时列过大问题解决办法
变量交换我们用到最多的就是比较数据了,但我们在面试时会碰到要不用第三个变量交换两个变量的值了,下面来给各位总结一些方法.

“PHP不用第三个变量交换两个变量的值”这个题看到过好多次了,看来面试确实喜欢考这道题。今天,对于这个题目,我自己总结了几种方法,可能不全,大家来互相补充。

方法一:使用字符串截取

<?php
$a = "fsdfds";
$b = "xiaorui";
$a = $a.$b;
$b = substr($a,0,strlen($a)-strlen($b));
$a = substr($a,strlen($b));
echo $a."-".$b;
?>

方法二:使用list()

<?php
 $a = "php";
 $b = "java";
 //list()不是函数,是语言结构,它是将数组中的值赋给一些变量
 list($a,$b) = array($b,$a);
 echo $a.'---'.$b;  //java---php
?>

方法三:使用数组分割

<?php
$a = "fsdfds";
$b = "xiaorui";
$b = $a."#$".$b;
$b = explode("#$",$b);
$a = $b[1];
$b = $b[0];
echo $a."-".$b;
?>

说明:这种方法也可以用于交换两个变量的值,但是这个方法听说好像不太标准,因为有人说这里的数组$b也算是一个新变量了(我有点不同意,看怎么理解了)。

方法四:使用异或运算

<?php
$a = "fsdfds";
$b = "xiaorui";
$a = $a^$b;
$b = $b^$a;
$a = $a^$b;
echo $a."-".$b;
?>

说明:这个方法是网上看到的,我仔细试了一下,发现这个居然是有BUG的。用次方法只能交换字符相同的两个字符串型的变量,不然结果是不正确的。

网上又找到一些方法


//字符串版本 结合使用substr,strlen两个方法实现
$a="a";
$b="b";
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';
$a.=$b;
$b=substr($a,0,(strlen($a)-strlen($b)));
$a=substr($a, strlen($b));
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

echo '-----------------------<br/>';

//字符串版本 使用str_replace方法实现
$a="a";
$b="b";
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';
$a.=$b;
$b=str_replace($b, "", $a);
$a=str_replace($b, "", $a);
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

echo '-----------------------<br/>';

//字符串版本 结合使用list方法和array实现
$a="a";
$b="b";
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';
list($b,$a)=array($a,$b);
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

echo '-----------------------<br/>';

//字符串和数字都适用 使用异或运算
$a='a';
$b='b';
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';
$a=$a^$b;
$b=$b^$a;
$a=$a^$b;
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

echo '-----------------------<br/>';

//只适用于数字
$a=3;
$b=5;
echo '交换前 $a:'.$a.',$b:'.$b.'<br />';
$a=$a+$b;
$b=$a-$b;
$a=$a-$b;
echo '交换后$a:'.$a.',$b:'.$b.'<br />';

[!--infotagslink--]

相关文章

  • java8如何用Stream查List对象某属性是否有重复

    这篇文章主要介绍了java8如何用Stream查List对象某属性是否有重复的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-11
  • R语言 如何删除指定变量或对象

    这篇文章主要介绍了R语言删除指定变量或对象的操作方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-06
  • JavaScript预解析,对象详解

    这篇文章主要介绍了JavaScript预解析,对象的的相关资料,小编觉得这篇文章写的还不错,需要的朋友可以参考下,希望能够给你带来帮助...2021-11-10
  • 学习JavaScript设计模式之装饰者模式

    这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • javascript设计模式之解释器模式详解

    神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
  • Postgresql 如何选择正确的关闭模式

    这篇文章主要介绍了Postgresl 如何选择正确的关闭模式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-18
  • 如何在Spring WebFlux的任何地方获取Request对象

    这篇文章主要介绍了如何在Spring WebFlux的任何地方获取Request对象,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下...2021-01-26
  • 牛叉的Jquery――Jquery与DOM对象的互相转换及DOM的三种操作

    只有jQuery对象才能调用jQuery类库的各种函数,同样有些dom对象的属性和方法在jQuery上也是无法调用的,不过基本上jQuery类库提供的函数包含了所有的dom操作。这就需要我们知道如何将jQuery对象和DOM的相互转换的方法。1...2015-10-30
  • 如何开启mysql中的严格模式

    很多集成的PHP环境(PHPnow WAMP Appserv等)自带的MySQL貌似都没有开启MySQL的严格模式,何为MySQL的严格模式,简单来说就是MySQL自身对数据进行严格的校验(格式、长度、类型等),比如一个整型字段我们写入一个字符串类型的数...2013-10-04
  • js如何打印object对象

    js调试中经常会碰到输出的内容是对象而无法打印的时候,光靠alert只能打印出object标示,却不能打印出来里面的内容,甚是不方便,于是各方面整理总结了如下一个函数,能够将数组或者对象这类的结果一一打印出来,具体代码如下: fu...2015-10-21
  • JavaScript设计模式之职责链模式

    这篇文章主要介绍了JavaScript设计模式之职责链模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
  • javascript self对象使用详解

    这篇文章主要介绍了javascript self对象使用详解的相关资料,需要的朋友可以参考下...2016-10-20
  • 替换json对象中的key最佳方案

    本文给大家介绍如何替换json对象中的key,通过实例代码给大家介绍key的替换方法,代码也很简单,需要的朋友参考下吧...2021-06-02
  • c#标准idispose模式使用示例

    下面将把C#里实现IDispose模式的代码展现出来,大家一起来学习一下,它的使用场合也很多的,当我们手动对网站,数据库作封装时,都会用的到...2020-06-25
  • 详解Javascript中的Object对象

    这篇文章主要介绍了详解Javascript中的Object对象,需要的朋友可以参考下...2016-03-01
  • C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?

    这篇文章主要介绍了C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?,这也小编做.NET项目时经常思考和让人混乱的一个问题,这篇文章写的挺好,一下清晰了许多,需要的朋友可以参考下...2020-06-25
  • Bootstrap媒体对象的实现

    在web页面中,图片居左,内容居右排列,是非常常见的效果,它也就是媒体对象,它是一种抽象的样式,可以用来构建不同类型的组件。本文给大家介绍Bootstrap媒体对象的实现,感兴趣的朋友一起学习吧...2016-05-04
  • 学习JavaScript设计模式之状态模式

    这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-12
  • ActiveX部件不能创建对象:dm.dmsoft代码:800A01AD

    vbs调用插件报:ActiveX部件不能创建对象,代码:800A01AD,一般是因为病毒导致dll文件丢失或者64系统问题导致,需要的朋友可以参考下...2020-06-30
  • 理解JavaScript事件对象

    这篇文章主要为大家介绍了JavaScript事件对象,了解JavaScript事件...2016-01-26