php State状态模式学习笔记

 更新时间:2016年11月25日 14:58  点击:1622
星际的一些兵种会有不止一种状态,比如坦克可以架起来,机枪兵可以打兴奋剂,甚至还有一些被动的,比如被虫族女王喷洒绿色液体后,敌人的行动变慢。

如果按照一般的思路,每次我们对一个小兵进行操作的时候,比如一辆坦克,我们都要用if判断他的状态,这样代码中会有很多的if,else或者swith。


不过我们可以发现,我们需要的是他在某个状态下的行为,如果把这些行为按照状态封装起来,就可以减少大量的判断。


待解决的问题:封装坦克的状态,让状态自己去控制行为。


思路:把状态作为属性,兵种类本身只控制状态的变化,具体的行为由状态类定义。


状态(State)模式示例:

 代码如下 复制代码

<?php

//坦克状态的接口

interface TankState

{

  //坦克的攻击方法

  public function attack();

}

//坦克普通状态

class TankState_Tank implements TankState

{

  //坦克的攻击方法

  public function attack()

  {

  //这里简单的输出当前状态

  echo "普通状态";

  }

}

//坦克架起来的状态

class TankState_Siege implements TankState

{

  //坦克的攻击方法

  public function attack()

  {

  //这里简单的输出当前状态

  echo "架起来了";

  }

}

//坦克类

class Tank

{

  //状态

  public $state;

  //坦克的攻击方法

  public function __construct()

  {

  //新造出来的坦克当然是普通状态

  $this->state = new TankState_Tank();

  }

  //设置状态的方法,假设参数为玩家点击的键盘

  public function setState($key)

  {

   //如果按了s

    if($key = 's')

    {

      $this->state = new TankState_Siege();

    }

   //如果按了t

    elseif($key = 't')

    {

      $this->state = new TankState_Tank();

    }

  }

  //坦克的攻击方法

  public function attack()

  {

  //由当前状态自己来处理攻击

  $this->state->attack();

  }

}

//新造一辆坦克

$tank = new Tank();

//假设正好有个敌人路过,坦克就以普通模式攻击了

$tank->attack();

//架起坦克

$tank->setState('s');

//坦克再次攻击,这次是架起模式

$tank->attack();

?>

用途总结:状态模式可以将和状态相关的行为和属性封装,除了切换状态时,其它地方就不需要大量的判断当前状态,只要调用当前状态的方法等。


实现总结:用一个接口规范状态类需要实现的方法,比如上面的TankState规定了attack()。把各个状态封装成类,将不同状态下的不同方法放入各自的状态类,比如上面的攻击方法,同时所有的状态执行接口。原来的事务类,比如上面的Tank类,只负责状态切换,一旦需要某一个方法的调用,只要交给当前状态就可以了

今天我看到有朋友在问preg_replace和str_replace函数的区别在哪里,下面我就来给大家整理了一些关于这两个函数的使用技巧,希望文章来给你带来帮助哦。

str_replace可查找替换常规字符,
preg_replace可查找替换回车换行字符(\r\n)
preg_replace常用在

 代码如下 复制代码


<meta name="description" content="<?php echo htmlspecialchars(utf_substr(preg_replace('/\r\n/','',str_replace(' ','',strip_tags($this->getDescription()))),400)) ?>">

内容的过滤,过滤回车换行(\r\n)等

 代码如下 复制代码

<a href="/%E5%8A%A8%E4%BD%9C%E5%86%92%E9%99%A9_1.html1">首页</a> <a href="/%E5%8A%A8%E4%BD%9C%E5%86%92%E9%99%A9_1.html0" class="a1">上一页</a>

用str_replace函数和preg_replace函数替换成

 代码如下 复制代码

<a href="/%E5%8A%A8%E4%BD%9C%E5%86%92%E9%99%A9_1.html">首页</a> <a href="/%E5%8A%A8%E4%BD%9C%E5%86%92%E9%99%A9_1.html" class="a1">上一页</a>

例子

 代码如下 复制代码

$pages = $keyword_data_db->pages;
$pages = str_replace('?page=', '', $pages);
$pages = preg_replace('/_([0-9]+).html([0-9]+)/', '_$2.html', $pages);
$pages = str_replace('_0.html', '_1.html', $pages);

再看个比较例子

 代码如下 复制代码


$str =
'111111110000000000000000000000000000000111000001000100010000010010000010010000010100000010
';
$str = str_repeat($str, 1);
$pattern1 = array('12345'=>'', '67891'=>'');
$pattern2 = array('a'=>'', '1234567890'=>'');
$pattern3 = '/12345|67891/';
$pattern4 = '/a|1234567890/';
$pattern5 = array('12345', '67891');
$pattern6 = array('a', '1234567890'); 
$t = microtime(true);

echo microtime(true)-$t, "/n";        //0.4768660068512    2.7257590293884  
$t = microtime(true);
for($i=0; $i<10000; $i++)
{
     preg_replace($pattern3, '', $str);
}
echo microtime(true)-$t, "/n";        //0.30504012107849    1.0864448547363 
$t = microtime(true);
for($i=0; $i<10000; $i++)
{
     preg_replace($pattern4, '', $str);
}
echo microtime(true)-$t, "/n";        //0.30298089981079    1.117014169693  
$t = microtime(true);
for($i=0; $i<10000; $i++)
{
     str_replace($pattern5, '', $str);
}
echo microtime(true)-$t, "/n";        //0.18029189109802    0.22510504722595 
$t = microtime(true);
for($i=0; $i<10000; $i++)
{
     str_replace($pattern6, '', $str);
}
echo microtime(true)-$t, "/n";        //0.18104100227356   0.23055601119995 
//说明:当str_repeat的第二个参数为1时输出第一个数字,当为8时输出第二个数字

区别

区别就是str_replace被替换(查找)的内容是固定的、确定的,当然可以使用变量,但是变量也表示固定的、确定的内容,比如可以完成把所有的\n替换为<br>等场合。

而preg_replace被替换(查找)的内容是用规则来描述的,比如可以把所有的<和>之间的内容(HTML代码)替换掉。当然preg_replace也可以用来替换固定内容。

根据以上规则,所有str_replace能做的事情preg_replace都能办到,但是preg_replace的速度要慢些,使用也要复杂些,所以我们应该尽力使用str_replace。

在这里我们可以利用strtotime函数与date函数同时使用来获取了,例子非常的简单在此我就不介绍其它的了,直接上代码。

PHP获得今天凌晨时间戳,百度了一下,没看见有,也可能是我理解错了。

直接上代码:

比如,今天是2102年11月2号,那么php要获取2102年11月2号的时间戳是怎么办的呢?

代码:echo strtotime(date('Y-m-d')),'

';


获取明天凌晨的时间戳

代码:echo strtotime(date('Y-m-d',strtotime('+1 day'))),'

';

最后再附一串代码

<?php
echo "今天:".date("Y-m-d")."<br>";    
echo "昨天:".date("Y-m-d",strtotime("-1 day")), "<br>";    
echo "明天:".date("Y-m-d",strtotime("+1 day")). "<br>"; 
echo "一周后:".date("Y-m-d",strtotime("+1 week")). "<br>";    
echo "一周零两天四小时两秒后:".date("Y-m-d G:H:s",strtotime("+1 week 2 days 4 hours 2 seconds")). "<br>";    
echo "下个星期四:".date("Y-m-d",strtotime("next Thursday")). "<br>";    
echo "上个周一:".date("Y-m-d",strtotime("last Monday"))."<br>";    
echo "一个月前:".date("Y-m-d",strtotime("last month"))."<br>";    
echo "一个月后:".date("Y-m-d",strtotime("+1 month"))."<br>";    
echo "十年后:".date("Y-m-d",strtotime("+10 year"))."<br>";   
strtotime()函数的作用是将日期时间描述解析为 Unix 时间戳
int strtotime  ( string time [, int now] )
?>

做程序开发的朋友应该都听说过设计模式这个词,对于做java开发的,应该一听到这个词就明白是什么意思,但对于做PHP的朋友来说,往往越看越迷糊,那到底什么是设计模式呢?其实作者也不懂,下面是从网上摘抄的关于设计模式的一些解释,期待能够有一些理解。

 


php设计模式有如下

备忘录模式(Memento模式)

观察者模式(Observer模式)

模板方法模式(Template Method模式)

命令模式(command模式)

合成模式(composite模式)

享元模式(flyweight模式)

策略模式(strategy模式)

状态模式(state模式)

适配器模式(adapter模式)

工厂方法模式(factory method模式)

原型模式(prototype模式)

门面模式(facade模式)

单例模式(singleton模式)

桥梁模式(bridge模式)

装饰器模式(decorator模式)

抽象工厂模式(abstract factory模式)

建造者模式(Builder模式)

访问者模式(Visitor模式)


当你在不断的试图从你的应用程序中发现新的特征时,你是否发现你提出的解决方法和一些以前你已经实现的东西是如此的类似呢?如果你是一个程序员(即使你才开始很短的时间),你都可能回答“是”。这看起来就是你使用了一些以前的代码来解决软件开发过程中新发现的问题了。你可能已经认识到:你的解决方法是基本原理,是一个不仅仅是你而且是所有专业开发者都能广泛重复应用的方法。

事实上,许多程序问题都不断的反复的遇到,而且许多用来解决这些问题的基本方法(或者说是设计模式)都已经浮现出来。设计模式就是一个教你如何利用真实可靠的设计来组织你的代码的模板。

设计模式历史

“设计模式”这个术语最初被设计用于建筑学领域。Christopher Alexander 在他1977的著作“A Pattern Language:Towns/Building/Construction”里面描述了一些常见的建筑学设计问题,并解释了如何用这些已有的,著名的模式集合来开始全新的有效的设计。Alexander的观点被很好的转化到软件开发上来,并且长期的用原有的组件来构造新的解决方案。

所有的设计模式都有一些常用的特性:一个标识(a name),一个问题陈述(a problem statement)和一个解决方案(a solution)。

1、一个设计模式的标识是重要的,因为它会让其他的程序员不用进行太深入的学习就能立刻理解你的代码的目的(至少通过这个标识程序员会很熟悉这个模式)。

2、问题描述是用来说明这个模式的应用的领域。

3、解决方案描述了这个模型的执行。一个好的设计模式的论述应该覆盖使用这个模型的优点和缺点。

一个模式是解决特定问题的有效方法。一个设计模式不是一个库(能在你的项目中直接包含和使用的代码库)而是一个用来组织你的代码的模板。事实上,一个代码库和一个设计模式在应用上是有很多不同的。

比如,你从店铺里面买的一件衬衫是一个代码库,它的颜色,样式和大小都由设计师和厂商决定,但它满足了你的需求。然而,如果店里面没有什么衣服适合你,那你就能自己创建自己的衬衫(设计它的形状,选择布料,然后裁缝在一起)。但是如果你不是一个裁缝,你可能会发现自己很容易的去找一个合适的模式然后按着这个模式去设计自己的衬衫。使用一个模型,你可以在更少的时间内得到一个熟练设计的衬衫。

回到讨论软件上来,一个数据提取层或者一个CMS(content management system)就是一个库,它是先前设计好而且已经编码好了的,如果它能准确的满足你的需要那它就是一个好的选择。

 

工厂模式

工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是 你要生成的对象对应的类名称。

 代码如下 复制代码

Example #1 调用工厂方法(带参数)
<?php
class Example
{
    // The parameterized factory method
    public static function factory($type)
    {
        if (include_once 'Drivers/' . $type . '.php') {
            $classname = 'Driver_' . $type;
            return new $classname;
        } else {
            throw new Exception ('Driver not found');
        }
    }
}
?>

按上面的方式可以动态加载drivers。如果Example类是一个数据库抽象类,那么 可以这样来生成MySQL和 SQLite驱动对象:
<?php
// Load a MySQL Driver
$mysql = Example::factory('MySQL');

// Load a SQLite Driver
$sqlite = Example::factory('SQLite');
?>
单例

单例模式(Singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。

Example #2 单例模式
<?php
class Example
{
    // 保存类实例在此属性中
    private static $instance;
   
       // 构造方法声明为private,防止直接创建对象
    private function __construct()
    {
        echo 'I am constructed';
    }

    // singleton 方法
    public static function singleton()
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }
   
    // Example类中的普通方法
    public function bark()
    {
        echo 'Woof!';
    }

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

}

?>

这样我们可以得到一个独一无二的Example类的对象。
<?php

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

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

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

?>

最后一个想法:就象一个裁缝模型,一个设计本身而言是没有什么用处的。毕竟,你不可能穿一个服装模型,它仅仅是由很薄的纸拼凑起来的。类似的,一个软件设计模型也仅仅只是一个引导。它必须根据程序设计语言和你的应用程序的特点和要求而特别的设计。

在php网站开发过程中有时候需要把结果集进行分组,使用php的内置函数array_chunk就可以实现
 代码如下 复制代码

<?php
$teams=array(1,2,3,4,5,6,7,8,9);
$teams=array_chunk($teams,2);
print_r($teams);
/*

Array

(

    
[0] => Array

        
(

            
[0] => 1

            
[1] => 2

        
)

 
    
[1] => Array

        
(

            
[0] => 3

            
[1] => 4

        
)

 
    
[2] => Array

        
(

            
[0] => 5

            
[1] => 6

        
)

 
    
[3] => Array

        
(

            
[0] => 7

            
[1] => 8

        
)

 
    
[4] => Array

        
(

            
[0] => 9

        
)

 
)

*/

?>

array_chunk() 函数把一个数组分割为新的数组块。
其中每个数组的单元数目由 size 参数决定。最后一个数组的单元数目可能会少几个。
可选参数 preserve_key 是一个布尔值,它指定新数组的元素是否有和原数组相同的键(用于关联数组),还是从 0 开始的新数字键(用于索引数组)。默认是分配新的键。

[!--infotagslink--]

相关文章

  • javascript设计模式之解释器模式详解

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

    这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • Postgresql 如何选择正确的关闭模式

    这篇文章主要介绍了Postgresl 如何选择正确的关闭模式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-18
  • 如何开启mysql中的严格模式

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

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
  • Smarty模板学习笔记之Smarty简介

    1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
  • c#标准idispose模式使用示例

    下面将把C#里实现IDispose模式的代码展现出来,大家一起来学习一下,它的使用场合也很多的,当我们手动对网站,数据库作封装时,都会用的到...2020-06-25
  • C# MVC模式中应该怎样区分应用程序逻辑(Controller层)和业务逻辑(Model层)?

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

    这篇文章主要介绍了JavaScript设计模式之职责链模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
  • php Observer观察者模式之学习笔记

    当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
  • 学习JavaScript设计模式之状态模式

    这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-12
  • Java接口DAO模式代码原理及应用详解

    这篇文章主要介绍了Java接口DAO模式代码原理及应用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-03
  • C#中的IDisposable模式用法详解

    这篇文章主要介绍了C#中的IDisposable模式用法,讲述了垃圾资源回收机制的实现,并对比分析了Dispose()方法、~DisposableClass()析构函数、虚方法Dispose(bool disposing)的原理,需要的朋友可以参考下...2020-06-25
  • 阿里云OpenSearch在php版sdk开启调试模式

    版本:php_v2.0.6 在CloudsearchClient的类中,开启debug模式,设置为true 如:$opts = array(&#39;host&#39;=>$host,&#39;debug&#39;=>true); 注意true不能加引号...2016-05-19
  • C#使用Dispose模式实现手动对资源的释放

    这篇文章主要介绍了C#使用Dispose模式实现手动对资源的释放,涉及C#采用Dispose模式操作资源的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • 学习JavaScript设计模式之单例模式

    这篇文章主要为大家介绍了JavaScript设计模式中的单例模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
  • MIUI儿童模式如何开启 小米手机儿童模式开启教程

    您是否遇到过孩子想要玩手机又不好拒绝,或者是您想要给孩子配一个联系用的手机有担心孩子玩手机上瘾?如果您购买的是小米手机,那么MIUI的儿童模式就能很好地解决这个问题...2016-12-21
  • JavaScript设计模式之命令模式

    这篇文章主要介绍了JavaScript设计模式之命令模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
  • PHP 日期函数 学习笔记介绍

    举一个简单的date例子 我将使用echo命令把内容输出到我们的客户端(浏览器)。我将使用下面的代码做为基础代码。 代码如下 复制代码 <!DOCTY...2016-11-25
  • PHP单例模式静态类解析和实现源代码

    我们建站的时候,开始是每次请求数据库都要重新连接的、这样显然不合理、然后自己封装了一个数据库操作类、DBTools.php、要解决一个连接多次使用的话、最好的办法是使...2016-11-25