- 浏览: 325785 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
ljl961890233bear:
...
利用MySQL Cluster 7.0 + LVS 搭建高可用环境 -
wang1352083:
$m->listDBs(); 返回的是一个有dbnam ...
MongoDB PHP API 及用法 -
走忽闪953:
...
putty PasswordAuthentication -
jxhgzs001:
很好 很强大,不顶你一下 觉得过意不去啊
cocos2d 的一些实用代码 -
lingtianlan:
我实际测试的结果却和你不一样,调用顺序是awakeFromNi ...
[转]loadView/viewDidLoad/initWithNibName/awakeFromNib/initWithCoder的用法
前段时间看到有人用魔兽来解释设计模式,感觉很有意思,于是我把它改了改,又添加了些设计模式内容,今天发出来。有些地方借鉴了前人的内容,没有注明,请前人不要见怪啊。
这里用大家感兴趣的魔兽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;
}
}
好了,到这里初始化代码就写好了,现在还差一个控制这些初始化得类,也就是封装他们:
<?php
class initialController {
//构造函数,参数为玩家的数组
public function __construct($playerArray)
{
foreach ($playerArray as $player)
{
switch ($player->race)
{
case 'NighyElf':
$initialController = new NighyElfInitial();break;
case 'ORC':
$initialController = new ORCInitial();break;
}
$initialController->giveArmy($player);
$initialController->giveBuilding($player);
$initialController->giveSupply($player);
}
}
}
最后就是简单这么一调用,就OK:
<?php
//有两个精灵族两个兽族
$playerArray = array(new player('NighyElf'), new player('NighyElf'), new player('ORC'), new player('ORC'));
//进行初始化工作
$initialController = new initialController($playerArray);
这就是策略模式,他将不同情况下的算法封装在一起。Zend framework中的Zend_Application_Resource就是用策略模式来设计的。
三、工厂模式:
问题的提出:
最初在设计模式一书中,许多设计模式都鼓励使用松散耦合。要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程。在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完全不相关的部分中也有可能出现级联破坏。
该问题在于紧密耦合。系统某个部分中的函数和类严重依赖于系统的其他部分中函数和类的行为和结构。您需要一组模式,使这些类能够相互通信,但不希望将它们紧密绑定在一起,以避免出现联锁。
在大型系统中,许多代码依赖于少数几个关键类。需要更改这些类时,可能会出现困难。例如,假设您有一个从文件读取的 User 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。
工厂模式是一种类,它具有为您创建对象的某些方法。您可以使用工厂类创建对象,而不直接使用 new。这样,如果您想要更改所创建的对象类型,只需更改该工厂即可。使用该工厂的所有代码会自动更改。
问题的解决:
呵呵,估计有些phper没看懂吧,没关系,那是我从其他地方抄的,我们下面还是通过魔兽来进行吧。这一部分,我看都已经有前人写好了,我就基本上照抄了,请前人不要见怪啊。呵呵。
前面选了暗夜精灵族(Nighy Elf),和兽族(ORC),因为小精灵(Wisp)能建造建筑,还能自爆。所以根据这个我们下面先写个小精灵(Wisp)的类。
<?php
class Wisp
{
private $mHealthPoint = 120;//这是小精灵的血量
private $mArmor = 0;//这是小精灵的护甲
//小精灵能建造建筑
public function Build()
{
echo '精灵建造建筑咯。<br/>';
}
//每个小精灵被造出来时还会占用一个人口
public function __construct()
{
echo '你已经建造了一个小精灵。<br/>';
//这里是增加已有人口的代码
}
//每个小精灵死亡会减少你占用的人口
public function __destruct()
{
//这里是减少已有人口的代码
}
}
把这些代码放在Arms/ Wisp.php中。
啊,还有还有,还有苦工(Peon)的类
<?php
class Peon
{
private $mHealthPoint = 250;//这是苦工的血量
private $mArmor = 0;//这是苦工的护甲
//苦工能建造建筑
public function Build()
{
echo '苦工建造建筑咯。<br/>';
}
//每个苦工被造出来时还会占用一个人口
public function __construct()
{
echo '你已经建造了一个苦工。<br/>';
//这里是增加已有人口的代码
}
//每个苦工死亡会减少你占用的人口
public function __destruct()
{
//这里是减少已有人口的代码
}
}
把这些代码放在Arms/ Peon.php中。
等等,这样岂不是很复杂,魔兽里面还有那么多的兵种,另外都还有两个种族,每次创建一个兵就要new一个,要是记不住这个兵的类名,岂不是new不了?而且如果一个兵是一个类,放在一个文件里,那是不是一开始就要把所有的几十上百个文件都include一次啊,那效率可想而知啊。
嘿嘿,当然是有解决办法的啊,我们再写一个类把这些类都封装起来,这个把兵种都封装起来的类我们称之为工厂类,他可以像生产产品一样,来创建兵,帮我们对其实例化。下面我们就来看这个类怎么实现吧。
<?php
class CreatArms
{
public function __construct(){}
public function Creat($arms,$path = '')
{
include $path.$arms.'.php'; //包含要这个类的文件
return new $arms; //返回你创建的兵种对象的句柄
}
}
这样,即使在兵种多样的情况下,我们仍然可以很方便地实例化:
$creator = new CreatArms();
$w1 = $creator->Creat('兵种名','前缀或路径');
例如创建小精灵:
$creator = new CreatArms();//不管创建啥,我都只要使用这个类
$w1 = $creator->Creat(‘Wisp’,’./Arms/’);//创建一个小精灵
$w1->Build();//让小精灵造建筑
这就是传说中的工厂模式,通过工厂模式,对于如论坛那种有很多种用户的,特别是为了以后扩展比较方便的,采用工厂模式,是个很好的解决方法。在zend framework中的Zend_Form、Zend_Filter、Zend_Validate就是用工厂模式来构架的。
四、观察者模式:
问题的提出:
观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。
问题的解决:
呵呵,上面还是抄的,看不懂没关系,我们今天重点是玩魔兽。
已经造了很长时间的兵了,现在可以出去带兵打仗了,如果我去打电脑的兽族,那么电脑与那个兽族同盟的精灵族就会过来帮忙。那么如何让他知道自己的同盟受攻击了呢。现在我们就来讨论这个问题。
首先我们写一下结盟的抽象类:
<?php
abstract class abstractAlly
{
//放置观察者的集合,这里以简单的数组来直观演示
protected $oberserverCollection;
//增加观察者的方法,参数为观察者(也是玩家)
public function addOberserver($oberserver)
{
$this->oberserverCollection[] = new oberserver($oberserver);
}
//将被攻击的电脑的名字通知各个观察者
public function notify($beAttackedPlayerName)
{
//把观察者的集合循环
foreach ($this->oberserverCollection as $oberserver)
{
//调用各个观察者的救援函数,参数为被攻击的电脑的名字,if用来排除被攻击的电脑的观察者
if($oberserver->name != $beAttackedPlayerName)
$oberserver->help($beAttackedPlayerName);
}
}
abstract public function beAttacked($beAttackedPlayer);
}
下面我们就写具体的结盟类:
<?php
class Ally extends abstractAlly
{
//构造函数,将所有电脑玩家的名称的数组作为参数
public function __construct($allPlayer)
{
//把所有电脑玩家的数组循环
foreach ($allPlayer as $player)
{
//增加观察者,参数为各个电脑玩家的名称
$this->addOberserver($player);
}
}
//将被攻击的电脑的名字通知各个观察者
public function beAttacked($beAttackedPlayerName)
{
//调用各个观察者的救援函数,参数为被攻击的电脑的名字,if用来排除被攻击的电脑的观察者
$this->notify($beAttackedPlayerName);
}
}
接着在二、策略模式中我们定义的player类中加入一个help方法
public help($beAttackedPlayerName)
{
//这里简单的输出,谁去救谁,最后加一个换行,便于显示
echo $this->name." help ".$beAttackedPlayerName."<br />";
}
这样就行了。最后就是仿真了。
<?php
//先设置敌方电脑
$allComputePlayer = array('NighyElf2', 'ORC2');
//新建电脑结盟
$Ally = new Ally($allComputePlayer);
//假设我进攻了电脑的兽族
$Ally->beAttacked('ORC2');
这样结盟的另一家就能接到通知,去救援。观察者模式主要就是用在这种情况下。可以将某个状态变化立即通知到相关的对象,相关的对象就可以采用相应的策略。例如,zend framework中的Zend_Message就是用的观察者模式。
好了,今天就玩到这里,以后有空再和大家一起玩魔兽啊。
这里用大家感兴趣的魔兽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;
}
}
好了,到这里初始化代码就写好了,现在还差一个控制这些初始化得类,也就是封装他们:
<?php
class initialController {
//构造函数,参数为玩家的数组
public function __construct($playerArray)
{
foreach ($playerArray as $player)
{
switch ($player->race)
{
case 'NighyElf':
$initialController = new NighyElfInitial();break;
case 'ORC':
$initialController = new ORCInitial();break;
}
$initialController->giveArmy($player);
$initialController->giveBuilding($player);
$initialController->giveSupply($player);
}
}
}
最后就是简单这么一调用,就OK:
<?php
//有两个精灵族两个兽族
$playerArray = array(new player('NighyElf'), new player('NighyElf'), new player('ORC'), new player('ORC'));
//进行初始化工作
$initialController = new initialController($playerArray);
这就是策略模式,他将不同情况下的算法封装在一起。Zend framework中的Zend_Application_Resource就是用策略模式来设计的。
三、工厂模式:
问题的提出:
最初在设计模式一书中,许多设计模式都鼓励使用松散耦合。要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程。在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完全不相关的部分中也有可能出现级联破坏。
该问题在于紧密耦合。系统某个部分中的函数和类严重依赖于系统的其他部分中函数和类的行为和结构。您需要一组模式,使这些类能够相互通信,但不希望将它们紧密绑定在一起,以避免出现联锁。
在大型系统中,许多代码依赖于少数几个关键类。需要更改这些类时,可能会出现困难。例如,假设您有一个从文件读取的 User 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。
工厂模式是一种类,它具有为您创建对象的某些方法。您可以使用工厂类创建对象,而不直接使用 new。这样,如果您想要更改所创建的对象类型,只需更改该工厂即可。使用该工厂的所有代码会自动更改。
问题的解决:
呵呵,估计有些phper没看懂吧,没关系,那是我从其他地方抄的,我们下面还是通过魔兽来进行吧。这一部分,我看都已经有前人写好了,我就基本上照抄了,请前人不要见怪啊。呵呵。
前面选了暗夜精灵族(Nighy Elf),和兽族(ORC),因为小精灵(Wisp)能建造建筑,还能自爆。所以根据这个我们下面先写个小精灵(Wisp)的类。
<?php
class Wisp
{
private $mHealthPoint = 120;//这是小精灵的血量
private $mArmor = 0;//这是小精灵的护甲
//小精灵能建造建筑
public function Build()
{
echo '精灵建造建筑咯。<br/>';
}
//每个小精灵被造出来时还会占用一个人口
public function __construct()
{
echo '你已经建造了一个小精灵。<br/>';
//这里是增加已有人口的代码
}
//每个小精灵死亡会减少你占用的人口
public function __destruct()
{
//这里是减少已有人口的代码
}
}
把这些代码放在Arms/ Wisp.php中。
啊,还有还有,还有苦工(Peon)的类
<?php
class Peon
{
private $mHealthPoint = 250;//这是苦工的血量
private $mArmor = 0;//这是苦工的护甲
//苦工能建造建筑
public function Build()
{
echo '苦工建造建筑咯。<br/>';
}
//每个苦工被造出来时还会占用一个人口
public function __construct()
{
echo '你已经建造了一个苦工。<br/>';
//这里是增加已有人口的代码
}
//每个苦工死亡会减少你占用的人口
public function __destruct()
{
//这里是减少已有人口的代码
}
}
把这些代码放在Arms/ Peon.php中。
等等,这样岂不是很复杂,魔兽里面还有那么多的兵种,另外都还有两个种族,每次创建一个兵就要new一个,要是记不住这个兵的类名,岂不是new不了?而且如果一个兵是一个类,放在一个文件里,那是不是一开始就要把所有的几十上百个文件都include一次啊,那效率可想而知啊。
嘿嘿,当然是有解决办法的啊,我们再写一个类把这些类都封装起来,这个把兵种都封装起来的类我们称之为工厂类,他可以像生产产品一样,来创建兵,帮我们对其实例化。下面我们就来看这个类怎么实现吧。
<?php
class CreatArms
{
public function __construct(){}
public function Creat($arms,$path = '')
{
include $path.$arms.'.php'; //包含要这个类的文件
return new $arms; //返回你创建的兵种对象的句柄
}
}
这样,即使在兵种多样的情况下,我们仍然可以很方便地实例化:
$creator = new CreatArms();
$w1 = $creator->Creat('兵种名','前缀或路径');
例如创建小精灵:
$creator = new CreatArms();//不管创建啥,我都只要使用这个类
$w1 = $creator->Creat(‘Wisp’,’./Arms/’);//创建一个小精灵
$w1->Build();//让小精灵造建筑
这就是传说中的工厂模式,通过工厂模式,对于如论坛那种有很多种用户的,特别是为了以后扩展比较方便的,采用工厂模式,是个很好的解决方法。在zend framework中的Zend_Form、Zend_Filter、Zend_Validate就是用工厂模式来构架的。
四、观察者模式:
问题的提出:
观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。
问题的解决:
呵呵,上面还是抄的,看不懂没关系,我们今天重点是玩魔兽。
已经造了很长时间的兵了,现在可以出去带兵打仗了,如果我去打电脑的兽族,那么电脑与那个兽族同盟的精灵族就会过来帮忙。那么如何让他知道自己的同盟受攻击了呢。现在我们就来讨论这个问题。
首先我们写一下结盟的抽象类:
<?php
abstract class abstractAlly
{
//放置观察者的集合,这里以简单的数组来直观演示
protected $oberserverCollection;
//增加观察者的方法,参数为观察者(也是玩家)
public function addOberserver($oberserver)
{
$this->oberserverCollection[] = new oberserver($oberserver);
}
//将被攻击的电脑的名字通知各个观察者
public function notify($beAttackedPlayerName)
{
//把观察者的集合循环
foreach ($this->oberserverCollection as $oberserver)
{
//调用各个观察者的救援函数,参数为被攻击的电脑的名字,if用来排除被攻击的电脑的观察者
if($oberserver->name != $beAttackedPlayerName)
$oberserver->help($beAttackedPlayerName);
}
}
abstract public function beAttacked($beAttackedPlayer);
}
下面我们就写具体的结盟类:
<?php
class Ally extends abstractAlly
{
//构造函数,将所有电脑玩家的名称的数组作为参数
public function __construct($allPlayer)
{
//把所有电脑玩家的数组循环
foreach ($allPlayer as $player)
{
//增加观察者,参数为各个电脑玩家的名称
$this->addOberserver($player);
}
}
//将被攻击的电脑的名字通知各个观察者
public function beAttacked($beAttackedPlayerName)
{
//调用各个观察者的救援函数,参数为被攻击的电脑的名字,if用来排除被攻击的电脑的观察者
$this->notify($beAttackedPlayerName);
}
}
接着在二、策略模式中我们定义的player类中加入一个help方法
public help($beAttackedPlayerName)
{
//这里简单的输出,谁去救谁,最后加一个换行,便于显示
echo $this->name." help ".$beAttackedPlayerName."<br />";
}
这样就行了。最后就是仿真了。
<?php
//先设置敌方电脑
$allComputePlayer = array('NighyElf2', 'ORC2');
//新建电脑结盟
$Ally = new Ally($allComputePlayer);
//假设我进攻了电脑的兽族
$Ally->beAttacked('ORC2');
这样结盟的另一家就能接到通知,去救援。观察者模式主要就是用在这种情况下。可以将某个状态变化立即通知到相关的对象,相关的对象就可以采用相应的策略。例如,zend framework中的Zend_Message就是用的观察者模式。
好了,今天就玩到这里,以后有空再和大家一起玩魔兽啊。
发表评论
-
she
2013-03-27 22:43 0把申购和收货纳入资产 ... -
PHP中插件机制的一种实现方案
2010-11-26 18:42 1497一篇不错的关于php插件 ... -
九个PHP很有用的函数
2010-08-09 12:10 1357下面是九个PHP中很有用的功能,不知道你用过了吗? 1. 函 ... -
百万级PHP网站架构工具箱
2010-08-09 11:08 1677在了解过世界最大的PHP站点,Facebook的后台技术后,今 ... -
图片服务器和WEB应用服务器相分离的简单方案
2010-08-06 12:45 8713只是简单说明一下原理,其它的自己探索吧:) 一、两个域名:w ... -
MongoDB PHP API 及用法
2010-04-06 13:00 9613上篇说过如何安装php - Mongo扩展,现在说一下Mong ... -
PHP开发部分关键词
2009-10-19 10:07 1097从别人那里看到,能学习到一半的话,已经是很不错了,加油 th ... -
PHP实现多服务器session共享之memcache共享
2009-08-19 10:07 1531再自定义一套session处理机制,关于session的实现方 ... -
ICE-高效的中间件平台,牛刀小试
2009-08-17 10:48 1408ICE 看起来是个好东西! ... -
今天无事,就试试一个php datagrid
2009-08-15 09:42 2012先贴代码: <?php include ... -
php字符过滤
2009-08-05 09:35 1532MYSQL特殊字符:mysql_escape_string() ... -
PHP缓存加速器:eAccelerator
2009-07-30 14:24 2311eAccelerator README for Linux 简 ... -
讲讲php的魔术方法
2009-07-30 09:49 1356PHP5.0后,php面向对象提成更多方法,使得php更加的强 ... -
(一)PHP设计模式之工厂模式
2009-07-27 14:24 965工厂模式在规模较小的环境中似乎有些大材小用。不过,最好还是学习 ... -
PHP的5种常见的设计模式
2009-07-27 14:22 9901.工厂模式 2.单例模式 也叫单元素模式 3.观察者模式 4 ... -
基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计
2009-07-21 12:36 1837前言:本文阐述的是一款经过生产环境检验的千万级数据全文检索(搜 ... -
amf使用简介
2009-07-13 16:07 2629最近需要用到amf 与flex ... -
Memcached在大型网站中应用
2009-06-25 09:45 1495memcached是一个高性能的分布式的内存对象缓存系统,通过 ... -
php 使用socket 与c通讯
2009-06-22 18:19 1307今天需要和c,进行通讯!!c程序员写了一个接口,我需要 ... -
PHP几个数组函数的区别
2009-06-17 10:10 1252刚才用到了数组合并的函数,去看了手册,现在记录下来他们的区别: ...
相关推荐
【PHP5 技巧集-从魔兽看PHP设计模式】是一个关于PHP编程技巧的文章集合,其中涉及了多种实用的PHP开发技术。文章标题暗示了作者可能通过魔兽世界这款游戏中的某些概念来阐述PHP的设计模式,这可能包括如何在PHP中...
辅助性公会公告/制度/语音等自由方便的在线编辑设计,使您不需要懂得网站设计也能完善自己的公会网站,免费稳定的系统升级,保证了系统的持久稳定发展,系统完美支持魔兽世界国服/台服,祝您使用愉快。 睿博!魔兽...
Yii 框架是基于组件的高性能 PHP 框架,专为开发Web 2.0应用程序而设计。本项目利用Yii实现了一个魔兽世界(World of Warcraft)的排名网站,旨在展示公会副本进度和个人成就进度,同时也具备装备查询功能。下面我们...
《魔兽世界行会信息获取PHP应用WoW Roster Live US详解》 魔兽世界,这款深受全球玩家喜爱的大型多人在线角色扮演游戏,其丰富的社区生态催生了许多周边工具。其中,“WoW Roster Live US”是一款专为美国服务器...
U9 ORPG登陆器是一款专为ORPG(Online Role Playing Game,即在线角色扮演游戏)设计的辅助工具,它为Warcraft III(魔兽争霸III)的游戏地图提供了自动保存和快速读取的功能,极大地提升了ORPG地图的游戏体验。...
3. **Web应用架构**:该应用可能采用了MVC(Model-View-Controller)设计模式,这是一种常见的Web应用架构,将数据处理(模型)、用户界面(视图)和业务逻辑控制(控制器)分离,提高了代码的可维护性和可扩展性。...
WoW DKP Leaderboard是一款基于开源软件理念设计的魔兽世界公会管理工具,主要用于处理和展示EQDKP系统的DKP(Dragon Kill Points)排行榜。在MMORPG(大型多人在线角色扮演游戏)中,DKP是一种常见的资源分配制度,...
Laravel作为PHP领域的一款热门框架,以其优雅的设计和丰富的功能受到开发者们的喜爱。本篇将详细介绍如何在Laravel项目中集成Battle.net API,为你的应用添加更多的游戏数据和元数据。 **一、Laravel 框架基础** ...
3. 模块化设计:WoWRoster_Live采用模块化结构,开发者可以根据需求添加或定制功能。如“modules”目录下的各种功能模块,可以扩展公会管理的各种场景。 4. 用户界面:通过“index.php”和“blocks”目录中的文件,...
TrinityCore通常用于魔兽世界(World of Warcraft)的私人服务器,它处理游戏的服务器端逻辑和数据库交互。 Laravel的模型提供了Active Record模式的实现,允许开发者通过面向对象的方式来操作数据库记录。例如,你...
MaNGOS本身是一个知名的开源MMORPG(大型多人在线角色扮演游戏)服务器软件,它允许用户创建自己的魔兽世界私人服务器。将MaNGOS与CMS结合,意味着这个系统不仅提供了游戏服务器的管理功能,还扩展到了社区交流和...