PHP设计模式装饰器模式实例

 更新时间:2016年11月25日 14:56  点击:2247
php面向对象的设计模式中有很多种模式了,今天我们为各位介绍的是装饰器模式的一个学习笔记了,有需要了解php装饰器模式的朋友可以和小编来看看。


我们在使用面向对象的日常开发过程中,或许会碰见需要对某个方法或者某个对象,添加新的行为。然而常见的做法是,写一个子类继承需要改写的类,然后去重新实现类的方法。

但是装饰器模式(Decorator),可以动态地添加修改类的功能,在使用装饰器模式,仅需在运行时添加一个装饰器对象既可实现,相对与生成子类更加的灵活。

在我们需要改写一个类的时候通常的做法是采用继承的方式来重新方法,如下代码

/*
 * 比如我们需要改写一串字符串的样式,采用继承的写法。
 */
class Canvas {
    function draw($width = 20, $height = 10) {
        for($i = 0; $i < $height; $i++) {
            for($j = 0; $j < $width; $j++) {
                echo '*';
            }
            echo '<br/>';
         }
     }
}
class Canvas2 extends Canvas {
    function draw($width = 20, $height = 10) {
        echo "<div style='color: red;'>";
        parent::draw($width, $height);
        echo "</div>";
    }
}
$Canvas2 = new Canvas2();
$Canvas2->draw();

对于上面的这种写法,假如我们需要多增加一个一种样式就需要多一个继承。接下来使用装饰器模式(Decorator)就会方便很多。

/*

 * 首先声明一个装饰器的接口

 */

interface DrawDecorator {

    function beforeDraw();

    function afterDraw();

}

接下来再分别添加两个装饰类,来继承接口,实现接口中的方法

/*
 * 颜色装饰
 */
class ColorDrawDecorator implements DrawDecorator {
    protected $color;
    function __construct($color = 'red') {
        $this->color = $color;
    }
    function beforeDraw() {
        echo "<div style='color: {$this->color};'>";
    }
    function afterDraw() {
        echo "</div>";
    }
}
/*
 * 字体大小装饰
 */
class SizeDrawDecorator implements DrawDecorator {
    protected $size;
    function __construct($size = '14px') {
        $this->size = $size;
    }
    function beforeDraw() {
        echo "<div style='font-size: {$this->size};'>";
    }
    function afterDraw() {
        echo "</div>";
    }
}

接下来就是使用我们前面所创建的装饰类

/*
 * 创建一个画布类
 */
class Canvas {
    protected $decorators = array(); //用来存放装饰的数组
    function draw($width = 20, $height = 10) {
        $this->beforeDraw();
        for($i = 0; $i < $height; $i++) {
            for($j = 0; $j < $width; $j++)
            {
                echo '*';
            }
            echo '<br/>';
        }
        $this->afterDraw();
    }
    //添加装饰器的方法
    function addDecorator(DrawDecorator $decorator) {
        $this->decorators[] = $decorator;
    }
    function beforeDraw() {
        foreach($this->decorators as $decorator) {
            $decorator->beforeDraw();
        }
    }
    function afterDraw() {
        $decorators = array_reverse($this->decorators);
        foreach($decorators as $decorator) {
            $decorator->afterDraw();
        }
    }
}
$Canvas = new Canvas();
$Canvas->addDecorator(new ColorDrawDecorator('red'));
$Canvas->addDecorator(new SizeDrawDecorator('9px'));
$Canvas->draw(20, 10);

原型模式和其它的模式相对有一些不同之处了,这个也是当然了所有的设计模式中的各种模式都有自己的特色了,下面一起来看看。


原型模式其实和工厂模式比较类似,都是用来创建对象的,只不过与工厂模式的实现不同。原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。这样就免去了类创建时重复的初始化操作了。原型模式适用于大对象的创建,因为在创建一个大对象时,需要很大的开销。如果每次都去new就会消耗很大,原型模式仅需从内存拷贝既可。

还是继续通过实例来向大家演示一下

<?php
/**
 * 抽象原型角色
 */
interface Prototype {
    public function clone_obj();
}
/**
 * 具体原型角色
 */
class Concrete implements Prototype{
 
    private $data;
 
    public function __construct($data) {
        $this->data = $data;
    }
    public function get_data() {
        return $this->data;
    }
 
    public function clone_obj() {
        /*
         * 深拷贝实现
         */
        /*$serialize_obj = serialize($this); // 序列化
        $clone_obj = unserialize($serialize_obj); // 反序列化 
        return $clone_obj;*/
 
        return clone $this; // 浅拷贝
    }
}
/**
 * 测试深拷贝用的引用类
 */
class Demo {
    public $arr;
}
$demo = new Demo();
$demo->arr = array(1, 2);
$concrete = new Concrete($demo);
$object1 = $concrete->clone_obj();
var_dump($concrete->get_data());
echo '<br />';
var_dump($object1->get_data());
echo '<br />';
//测试深拷贝
$demo->arr = array(3, 4);
var_dump($concrete->get_data());
echo '<br />';
var_dump($object1->get_data());
echo '<br />';
?>

更多的详细说明和实例

Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,下面我们就一起来看一篇简单的solr从数据库导入数据的例子

1. 先在本地的solr_db库下建一张solr_tb表(字段:id,name,price,desc),添加了5条数据,如下图。

建立数据表

2. 还记得上篇中安装solr的目录结构吗?打开D:\phpServer\solr\solr1\home\collection1\conf目录,暂且称这个目录为“配置文件目录”了。打开配置文件目录下的solrconfig.xml文件,在此文件的<config></config>标签之间的任一地方(最好是前面)添加如下代码:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
  <lst name="defaults">
    <str name="config">data-config.xml</str>
  </lst>
</requestHandler>

配置dataimport

3. 在当前目录下新建一个名为data-config.xml的文件,在文件中添加如下配置信息,此信息为你要连接的mysql库的信息,请如实填写(数据库为solr_db,数据表为solr_tb)。
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
 <dataSource type="JdbcDataSource"
  driver="com.mysql.jdbc.Driver"
  url="jdbc:mysql://127.0.0.1/solr_db"
  user="root"
  password="root" />
 <document>
  <entity name="solr_tb" transformer="DateFormatTransformer"
  query="select id,name FROM solr_tb where id >= ${dataimporter.request.id}">
 </entity>
 </document>
</dataConfig>

4. 找到同级目录下面的schema.xml(字段配置)文件,先将此文件备份一下,然后打开schema.xml,全选->删除,再将下面这段粘贴到schema.xml文件中。因为我们暂时用不到那么多参数,所以为了便于初学和理解,简化了一下。
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
  <!-- 要建立的索引,_version_这个不能省略 -->
  <fields>
    <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
    <field name="name" type="text_general" indexed="true" stored="true" />
    <field name="_version_" type="long" indexed="true" stored="true"/>
  </fields>
  <!-- 字段类型,配置上面字段<field>中出现的类型即可 -->
  <types>
    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
    <!-- text_general能对中文分词 -->
    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>
  </types>
  <!-- 唯一字段 -->
  <uniqueKey>id</uniqueKey>
  <!-- 设置默认查询字段,设置此处为name后,还要在solrconfig.xml中设置name="/select"中为<str name="df">name</str>。-->
  <defaultSearchField>name</defaultSearchField>
  <!-- 查询转换模式,是并且还是或者(and/or) -->
  <solrQueryParser defaultOperator="OR"/>
</schema>

说明一下:“<fields>”标签,就是配置你要建立索引的字段。我现在需要建立id,name两个字段,
即 <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/> 和 <field name="name" type="text_general" indexed="true" stored="true" /> 也就是对应第3步中select id,name FROM solr_tb这里的字段。了解一下fields标签。

5.在D:\phpServer\solr\dist目录中复制solr-dataimporthandler-4.7.0.jar、solr-dataimporthandler-extras-4.7.0.jar和mysql-connector-java-5.1.7-bin.jar(这个没有?点击下载)复制到D:\phpServer\solr\solr1\tomcat\webapps\solr\WEB-INF\lib目录中。

6.重启tomcat服务,访问http://localhost:8080/solr/,在左侧的菜单中的下拉选择collection1,然后再载入的菜单中选择Dataimport选项,是不是已经出现了如下图所示的界面呢。如果出现则表示成功了。接着按如下图的指示,现在开始导入数据吧!




solr导入数据

 

 
注:Custom Parameters 参数是第3步select语句中的id >= ${dataimporter.request.id},这里填id=1,即从id为1的数据开始导入,这样对于数据较大的表,可以控制分成几步导入。


Clean选项表示是否删除未匹配到的数据,也就是在数据库select结果中没有,而solr索引库中存在的时候,则删除。

 

8.出现如下图所示的界面则表示导入成功了。




导入数据成功

 

 
9.现在点击左侧的Query切换到查询页面,查看一下吧。




结果1




结果2

单例模式这个东西我相信有许多的朋友都不了解了,今天既然有学习到单例模式我就给各位整理一些小编学习用到的参考内容供各位学习。


1.定义

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。

2.解决的问题/使用场景

在数据库应用方面,使用单例模式,可以避免大量的new操作消耗的资源。
如果在系统中需要一个类来全局控制某些配置信息,那么使用单例模式可以很方便的实现。

3.实现单例模式的要点

需要一个保存类的唯一实例的静态成员变量。
构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义。
需要提供一个访问这个实例的静态方法(一般为getInstance方法),返回实例的引用。

4.实现代码示例

<?php

class Singleton

{

    private static $instance;

    private $conn;

 

    private function __construct()

    {

        $this->conn = mysql_connect(...);

    }

 

    private function __clone()

    {

    }

 

    public static function GetInstance()

    {

        if (!(self::$instance instanceof self))

        {

            slef::$instance = new self();

        }

        return self::$instance;

    }

 

    public function GetDbConnect()

    {

        return $this->conn;

    }

 

    public function selectData($sql)

    {

        // $result mysql_query($sql,$this->conn);

        // while mysql_fetch_array($result)....

    }

}

 

$db = Singleton::GetInstance();

$db->selectData("select * from user");

php数组为空我们可以通过很多php自带函数来实现了,下面小编就为各位整理了不少的判断数组是否为空的函数,希望对各位会带来帮助。


判断数组是否为空 使用这个函数就好了 count 如果输出为0的话 那么就这个数组就是空的的下面就是简单的测试代码了。php 判断数组是否为空 代码列子
 
<?php
$arr = array();
echo count($arr);
?>
 
输出为 0 的话数组为空

PHP判断数组为空方法2:empty($arr);

$arr= array("");
$result = empty($arr);
//$result = false
$arr = array();
$result = empty($arr);
//$result = true

PHP判断数组为空之一、for循环

最简单也是最直接的方法,用for循环来遍历数组。对于已知维数的数组可以判断,但如果是未知的多维数组,该怎么办?

PHP判断数组为空之二、implode();

用implode()将数组输出为字符串,判断输出的字串是否为空。初看上去似乎是个不错的方法,可惜跟上一点一样,对于二维以上数组就不行了。举个例子:

$arr= array(array(),array(),array());
$str = implode(',',$arr);
if(empty($str)) echo "空";
else echo "非空";

很明显$arr是个含有三个空数组的二维数组,应该也算是空的,可是输出的确是非空。判断失败。
PHP判断数组为空之三、count();

$arr= array("","","");
echo count($arr);

PHP判断数组为空之四、in_array('', $arr));

$arr= array("d","s","");
echo in_array('', $arr);

这个只能说明数组中有空的元素,不能证明数组是空的。很明显也不行。

PHP判断数组为空之五、empty();

这个cpyeh觉得跟前面几种方法差不多

$arr= array("","","");
if(empty($arr)) echo "空";
else echo "非空";
结果还是非空

PHP判断数组为空之六、用strlen(),没内容的话好象长度都为1
我们还可以在以上例子上加一句print_r($arr);看看。

[!--infotagslink--]

相关文章

  • photoshop设计一幅大鱼海棠动画片海报制作实例教程

    今天小编在这里就来给各位photoshop的这一款软件的使用者们来说一说设计一幅大鱼海棠动画片海报制作的实例教程,各位想知道具体制作步骤的使用者们,那么各位就快来看看...2016-09-14
  • javascript设计模式之解释器模式详解

    神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
  • ps怎么制作倒影 ps设计倒影的方法

    ps软件是一款非常不错的图片处理软件,有着非常不错的使用效果。这次文章要给大家介绍的是ps怎么制作倒影,一起来看看设计倒影的方法。 用ps怎么做倒影最终效果&#819...2017-07-06
  • C语言程序设计第五版谭浩强课后答案(第二章答案)

    这篇文章主要介绍了C语言程序设计第五版谭浩强课后答案(第二章答案),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-04-02
  • 学习JavaScript设计模式之装饰者模式

    这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • Photoshop设计商务名片的5种常见思路分享

    今天小编在这里就来给Photoshop的这一款软件的使用者们来说下计商务名片的5种常见思路,各位想知道的使用者,那么下面就快来跟着小编一起看一看吧。 给各位Photosho...2016-09-14
  • WPF实现类似360安全卫士界面的程序源码分享

    最近在网上看到了新版的360安全卫士,感觉界面还不错,于是用WPF制作了一个,时间有限,一些具体的控件没有制作,用图片代替了。感兴趣的朋友一起跟着小编学习WPF实现类似360安全卫士界面的程序源码分享...2020-06-25
  • photoshop安卓和苹果界面设计之尺寸规范详解

    今天小编在这里就来给各位photoshop的这一款软件的使用者们来说下安卓和苹果的界面设计之尺寸规范,各位想知道的使用者们,那么下面就快来跟着小编一起看看吧。 给...2016-09-14
  • photoshop设计重影效果具体制作教程

    今天小编在这里就来给各位photoshop的这一款软件的使用者们来说一说设计重影效果具体的制作教程,各位想知道具体制作方法的软件使用者们,那么大家就来看下小编带来的教...2016-09-14
  • JavaScript设计模式之职责链模式

    这篇文章主要介绍了JavaScript设计模式之职责链模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
  • PS怎么设计T恤 PS制作T恤教程

    PS怎么设计T恤?很多人都想要在T恤上有自己喜欢的图案,那么自己设计T恤的图案是方法之一,本次为大家带来了详细的ps设计T恤教程,有兴趣的同学快来看看吧。 1、打开PS,新...2016-12-31
  • Illustrator结合photoshop设计可爱的卡通女厨师头像制作教程

    今天小编在这里就来给Illustrator的这一款软件的使用者们来说一说结合photoshop设计可爱的卡通女厨师头像的制作教程,各位想知道具体制作步骤的使用者们,那么下面就快来...2016-09-14
  • photoshop设计一张节约用水环保主题海报制作教程

    今天小编在这里就来给photoshop的这一款软件的使用者们来详细的说说设计一张节约用水环保主题海报的制作教程,各位想知道具体制作方法的使用者们,那么下面就快来跟着小...2016-09-14
  • 学习JavaScript设计模式之状态模式

    这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-12
  • 学习JavaScript设计模式之单例模式

    这篇文章主要为大家介绍了JavaScript设计模式中的单例模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • JavaScript设计模式之命令模式

    这篇文章主要介绍了JavaScript设计模式之命令模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
  • c#实现51单片机频率计的代码分享(数字频率计设计)

    c#实现51单片机频率计的代码分享,大家参考使用吧...2020-06-25
  • 学习JavaScript设计模式之责任链模式

    这篇文章主要为大家介绍了JavaScript设计模式中的责任链模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • photoshop设计蜘蛛侠纹理文字效果制作教程

    今天小编在这里就来给给各位photoshop的这一款软件的使用者们来说一说设计蜘蛛侠纹理文字效果的制作教程,各位想知道具体制作步骤的使用者们,那么大家下面就来跟着小编...2016-09-14
  • Photoshop设计武侠风毛笔字效果教程

    今天小编在这里就来给Photoshop的这一款软件的使用者们说下设计武侠风毛笔字效果得教程,各位想知道到底该怎么射击制作的使用者们,那么下面就快来跟着小编一起看一看制...2016-09-14