从魔兽争霸看PHP设计模式

前段时间看到有人用魔兽来解释设计模式,感觉很有意思,于是我把它改了改,又添加了些设计模式内容,今天发出来。有些地方借鉴了前人的内容,没有注明,请前人不要见怪啊。

这里用大家感兴趣的魔兽3来讨论PHP的几种常见的设计模式:单件模式、策略模式、工厂模式、观察者模式。今天就讲这四个吧,以后继续。

这些设计模式,都是针对面向对象来说的,所以都用PHP5,另外在这里我想说的是PHP4从2008年8月8日(我记得是和北京奥运会同一天,没查证,呵呵)的时候官方就发了最后一个PHP4的补丁,这意味这PHP4的时代已经终结,所以,我建议大家现在就别理PHP4吧,就以PHP5来说吧。

一、单件模式:

问题的提出:

某些应用程序资源是独占的,因为有且只有一个此类型的资源。例如,通过数据库句柄到数据库的连接是独占的。您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销,在获取单个页面的过程中更是如此。

问题的解决:

那么下面我们就开始玩魔兽吧。首先双击war3.exe,这时候就开始运行魔兽了。我们用代码来实现吧。

<?php
class War3
{

public function __construct()

{

echo "War3 is Running.","<br />";

}
}
$war = new War3();

运行!很好,输出

War3 is Running.

我们已经可以开始游戏了,但是,如果我在代码末尾再加入

$war2 = new War3();

$war3 = new War3();

会怎么样呢?我们试试,输出结果:

War3 is Running.

War3 is Running.

War3 is Running.

完了,如果不小心双击了两次就开了3个魔兽,那如果再双击几次,那电脑肯定爆掉。。。我们还是来想想解决方法吧。

既然我们不能这么随意的就把这个类实例化了,那么我们就把构造函数改成私有方法。

class War3
{

private function __construct()

{

echo "War3 is Running.","<br />";

}
}

可是私有变量外部是无法访问的,这样以来,我们就连一个都打不开了啊。别急,我们再给他加一个不用通过实例化,外部也能访问的函数,那就是静态函数,
class War3
{

private function __construct()

{

echo "War3 is Running.","<br />";

}

public static function runWar()

{

}
}

通过这个静态的方法runWar()我们来控制类War3的实例化,那么还缺上一个标识,我们再创建一个标识,通过这个标识来表示我们的类是否已经实例化,如果实例化,直接返回句柄就行了。

把类修改成

class War3
{

protected static $_instance = null;

private function __construct()

{

echo "War3 is Running.","<br />";

}

public static function runWar()

{

if (null === self::$_instance) {

self::$_instance = new self();

}

return self::$_instance;

}
}

当然,我们运行魔兽时的实例化也要换种方法,就通过
$war = War3::runWar();
就能开始玩魔兽了,好了,下面把完整的代码附上来:

<?php
class War3
{

protected static $_instance = null;

private function __construct()

{

echo "War3 is Running.","<br />";

}

public static function runWar()

{

if (null === self::$_instance) {

self::$_instance = new self();

}

return self::$_instance;

}
}

$war = War3::runWar();
$war2 = War3::runWar();
$war3 = War3::runWar();

运行一下,结果是:

War3 is Running.

太好了,我双击了这么多次,也就只运行了一个魔兽,现在随便你怎么打开,机子都不会爆掉了。

这就是传说中的单价模式,主要用于一些很占资源的而且实例仅有一个实例就够用的东西,比如,zend framework中的Zend_Controller_Front前端控制器,就是采用单价模式来设计的,大家有兴趣的话可以看看那个。

二、策略模式:

问题的提出:

在此模式中,算法是从复杂类提取的,因而可以方便地替换。例如,如果要更改搜索引擎中排列页的方法,则策略模式是一个不错的选择。思考一下搜索引擎的几个部分 —— 一部分遍历页面,一部分对每页排列,另一部分基于排列的结果排序。在复杂的示例中,这些部分都在同一个类中。通过使用策略模式,您可将排列部分放入另一个类中,以便更改页排列的方式,而不影响搜索引擎的其余代码。

问题的解决:

呵呵,不讲那么复杂,刚才魔兽好不容易打开了,我们还是玩魔兽好了。
下面我们选battle,哇好多种族啊,有人族(Human),兽族(ORC),暗夜精灵族(Nighy Elf),不死族(Undead)。我选精灵族(Nighy Elf),再选一个精灵族和两个兽族(ORC),一个兽族和我是一家的,另一个精灵族和兽族是另一家的。

每一个玩家在进入游戏后都会得到一些资源,如一个大厅,五个小精灵(苦工)和一个矿山。这些可以称为是初始化的一些东西,这里我们就可以用到策略模式来封装这些初始化。

进入正题,首先我们来构建一个玩家类:

<?php
class player
{

//玩家名字

protected $_name;

//种族

protected $_race;

//队伍

protected $army;

//建筑

protected $building;

//人口

protected $population;

//黄金

protected $gold;

//木材

protected $wood;

//构造函数,设定所属种族

public function __construct($race)

{

$this->race = $race;

}

//__get()方法用来获取保护属性

private function __get($property_name)

{

if(isset($this->$property_name)) {

return($this->$property_name);

}

else {

return(NULL);

}

}

//__set()方法用来设置保护属性

private function__set($property_name,$value)

{

$this->$property_name=$value;

}
}

接着,我们再建一个玩家初始化的接口,

<?php
interface initialPlayer
{

//制造初始化的部队

public function giveArmy($player);

//制造初始化的建筑

public function giveBuilding($player);

//初始化资源

public function giveSource($player);
}

好了,到这里我们就该对这个接口来实现了,为了方便,我只选了两个种族,就只写这两个种族的初始化了:

首先是精灵族:

<?php
class NighyElfInitial implements initialPlayer
{

//制造初始化的部队

public function giveArmy($player)

{

//五个小精灵

for($i=0; $i<=5;$i++)

{

$creator = new CreatArms();//这个是创建部队类,在后面得工厂模式中会用到,这里我就不多说了

$player->army[] = $creator->Creat('Wisp','./Arms/');

}

}

//制造初始化的建筑

public function giveBuilding($player)

{

$creator = new CreatBuildings();

//一个基地

$player->building[] = $creator->Creat('TownHall','./Buildings/');

//一个矿场

$player->building[] = $creator->Creat('Mine','./Buildings/');

}

//初始化人口上限

public function giveSource($player)

{

$player->population= 10;

$player->gold= 1000;

$player->wood= 100;

}
}

接下来是兽族:

<?php
class ORCInitial implements initialPlayer
{

//制造初始化的部队

public function giveArmy($player)

{

//五个苦工

for($i=0; $i<=5;$i++)

{

$creator = new CreatArms();//这个是创建部队类,在后面得工厂模式中会用到,这里我就不多说了

$player->army[] = $creator->Creat('Peon','./Arms/');

}

}

//制造初始化的建筑

public function giveBuilding($player)

{

$creator = new CreatBuildings();

//一个基地

$player->building[] = $creator->Creat('TownHall','./Buildings/');

//一个矿场

$player->building[] = $creator->Creat('Mine','./Buildings/');

}

//初始化人口上限

public function giveSource($player)

{

$player->population= 10;

$player->gold= 1000;

$player->wood= 100;

}
}

时间: 2024-08-01 14:19:32

从魔兽争霸看PHP设计模式的相关文章

站在富士康的厂房里看建造者设计模式

自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onLayout源码详尽分析 自定义View系列教程04–Draw源码分析及其实践 自定义View系列教程05–示例分析 自定义View系列教程06–详解View的Touch事件处理 自定义View系列教程07–详解ViewGroup分发Touch事件 自定义View系列教程08–滑动冲突的产生及其处理

设计模式总结

原文:设计模式总结       从七月份开始一直到九月底才看完设计模式,在这个过程中我不敢说我已经掌握了那本书里面的内容,或者说1/5,没能力说也没有资格说.但是结果不重要,重要的是这个过程我的收获!主要包括如下几个方面:       1.认识了这么多设计模式.刚刚接触java没多久就在学长那里听过设计模式的大名,但是由于能力有限,一直不敢触碰.而今有幸将其都认识了.       2.开始有设计的理论了.在接触设计模式之前没有怎么想过设计方面东东,看到问题就立马动手解决,没有想到怎么样来设计更好

23种 设计模式---面向对象的基本原则

软件开发原则 原则1:不要重复自己(Don't Repeat Yourself,DRY原则)  这个原则非常重要,换言之,就是不要写重复的代码. 原则2:尽量简单.一目了然(Keep it Simple Stupid,KISS原则) 所以做到简单的同时,还要做到一目了然.你也可以这样理解,将一个软件做得连白痴都会用.这就是用户体验的最高境界了.如何做到简单且一目了然呢?这要归结到软件开发的可维护性和可理解性 原则3:适可而止(You Ain't Gonna Need It,YAGNI原则)  Y

设计模式序章

原文 设计模式序章  自大我进入程序员这行以来,总会听到设计模式 这几个字,当是的我并不是很懂,引用一句话:"虽然不懂你们在说什么,貌似很厉害的样子",大牛才会用到的东西,高端而又神秘!      到目前为止虽然多次听到大家说设计模式,但是目前的工作上 追求的都是 短平快,所以设计模式这方面接触的到不是特别的多,当然,简单的单例模式,抽象工厂,代理模式等 还是略微懂点的,O(∩_∩)O~.      我觉得很有必要研究下设计模式,设计模式被这么多人念叨这么久 ,肯定是有他强大的一面的.

设计模式之iterator模式到STL中iterator迭代器

设计模式之iterator模式到STL中iterator迭代器 近日看<设计模式:可复用面向对象软件的基础>一书中23种模式中就有iterator迭代模式,且篇幅颇大.机缘巧合.我在分析STL代码结构的时候,同样发现iterator迭代器,且占据相当大的地位. 从设计模式的角度来看iterator模式 ü     意图 提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露对象的内部表示.我想GOF 的意图这次说的很明白了,就是我想遍历一个聚合对象.但又隐藏内部实现.该怎么办呢?本模式主要

一句话评论设计模式六大原则

原文链接:http://www.cnblogs.com/lancidie/archive/2012/02/03/2337168.html        原则,故名思议则是本质的意思.所谓擒贼先擒王,研究设计模式自然要先了解设计原则,所有的模式都是在这些原则的基础之上发展起来的,有的是侧重一个,有的是多个都有所涉及.看完设计模式之后,我感觉到每个模式都有这些原则的影子,还渗透着面向对象的三大属性,也觉得这些原则也都有相通之处,,正是有了他们才使我们由代码工人转为艺术家.下面我来点评一下六大原则,望

java-JAVA 策略设计模式,为什么抽象策略类必须是一个抽象类,而不能是一个接口?

问题描述 JAVA 策略设计模式,为什么抽象策略类必须是一个抽象类,而不能是一个接口? 解决方案 可以是接口.但是GoF的书是按照C++写的,而C++没有接口,只有抽象类.很多人照抄到Java,还是用的抽象类. 解决方案二: 而且作为Java,如果是Java 7或者以前,最好的做法就是用接口,因为Java不支持多继承.而Java 8,最好用Lambda表达式. 解决方案三: 抽象类的作用在于多个类都需要用到的时候,提供方便,在开发中更加高效开发 解决方案四: 可以使用接口的啊,建议楼主找一个用J

【开源】QuickPager 分页控件的内部结构,和OO原则与设计模式

  关键字:提出需求.需求分析.原则.设计模式.索引        先说一下讨论的范围:使用数据库保存信息的项目,b/s结构,asp.net编写.请不要讨论这个范围之外的事情哦,谢谢!        这里想说的并不仅限于一个控件,而是一个关于分页的解决方案.信息都是放在数据库里的,在b/s结构里面一次提取所有的数据显示并不是一个好的方法,所以就需要一个把数据分成多个页的形式来显示.关于分页的解决方案有多种,一种实现方式可以用一个"分页控件"(我的解决方案),也可以用其他的方式来体现(比

.NET简谈设计模式之(装饰者模式)

装饰者模式其实有点难以理解,特别是对初学者来说可能有点晕,因为它的概念互相冲突,哪里互相冲突我们下面会讲解到. 本人保持一贯的写作风格,重在入门.在本人的这篇文章中会用一个比较恰当的比喻来让我们对问题迎刃而解,例子虽然简单但是重点突出. 在写这篇文章之前我在网上大概搜了一下关于"装饰者模式"的一些文章,但是讲解的效果都不太理想.要么就是找书搬过来的,要么就是对着书的例子从新创造一个.我看了大概三四篇这样子,不行看着头晕.文章的主人很想把问题的关键说清楚,但是很少能在原有代码的基础上画龙