星际争霸允许玩家作弊,当然这是在人和电脑对战的时候。而且作弊有个特点,比如快速建造,能量无限是对所有的玩家(包括电脑)都生效,如果关闭了作弊,对所有的玩家的作用都同时消失。
这也就是说如果我们把作弊状态作为一个类,他只能有一个对象。
待解决的问题:确保某个类只能有一个对象。
思路:把对外新建对象的权利都收回,包括new,clone。为了防止通过子类来覆盖父类的方法和成员,将类设置为final。用static成员来保存唯一的对象
单件模式示例:
<?php
//将类设置为final,禁止其他类继承它
final class cheat {
//快速建造的生效状态,用private保护
private $fastBuild = false;
//用static成员来保存唯一的对象
private static $instance;
//设置快速建造的生效状态的方法,用public为了能够公开调用
public function setStatus($input)
{
//如果输入的秘籍正确,operation cwal是快速建造的秘籍
if($input === 'operation cwal')
{
//像开关一样,逆反状态
$this->fastBuild = !$this->fastBuild ;
}
}
//读取快速建造的生效状态的方法,用public为了能够公开调用
public function getStatus()
{
return $this->fastBuild ;
}
//获取唯一对象的唯一方法
public function getInstance()
{
//如果对象没有被新建,则新建它
if(!isset(self::$instance))
{
self::$instance = new cheat() ;
}
return self::$instance ;
}
//用private来禁止在本类以外new对象
private function __construct(){}
//用private来禁止在本类以外clone对象
private function __clone
(){}
}
//获取作弊对象的唯一办法
$cheatInstance = cheat::getInstance();
//现在输出为0(这和操作系统有关,有些可能输出false,最好用var_dump来代替echo)
echo $cheatInstance->getInstance();
//输入秘籍
$cheatInstance->setInstance('operation cwal');
//现在输出为1(这和操作系统有关,有些可能输出true,最好用var_dump来代替echo)
echo $cheatInstance->getInstance();
//再次输入秘籍,取消作弊
$cheatInstance->setInstance('operation cwal');
//现在输出为又变成0(这和操作系统有关,有些可能输出false,最好用var_dump来代替echo)
echo $cheatInstance->getInstance();
?>
星际里面有些特殊的秘籍,比如无敌和增加矿,这是仅仅对于人玩家产生作用,对电脑玩家没有作用(大家都无敌还怎么玩)。我们希望有个人类作弊的类来继承作弊类,而子类中新增一些秘籍,比如无敌。单件模式不允许继承,我们可以采用单态模式。
单态模式不是通过唯一对象来保持一致,它将相关的成员设置为static,这样即使存在很多个它的对象,但它们共享成员,保持状态的一致。同时也允许继承。
<?php
//不使用final,允许继承
class cheat {
//快速建造的生效状态,用private保护,同时设置static让所有的作弊对象共享
private static $fastBuild = false;
//设置快速建造的生效状态的方法,用public为了能够公开调用
public function setStatus($input)
{
//如果输入的秘籍正确,operation cwal是快速建造的秘籍
if($input === 'operation cwal')
{
//像开关一样,逆反状态
self::$fastBuild = !self::$fastBuild ;
}
}
//读取快速建造的生效状态的方法,用public为了能够公开调用
public function getStatus()
{
return self::$fastBuild ;
}
}
//新增一个作弊对象
$cheatInstance1 = new cheat();
//现在输出为0(这和操作系统有关,有些可能输出false,最好用var_dump来代替echo)
echo $cheatInstance1->getInstance();
//输入秘籍
$cheatInstance1->setInstance('operation cwal');
//现在输出为1(这和操作系统有关,有些可能输出true,最好用var_dump来代替echo)
echo $cheatInstance1->getInstance();
//新增一个作弊对象
$cheatInstance2 = new cheat();
//现在也是输出为1,因为它们共享$fastBuild
echo $cheatInstance2->getInstance();
?>
作弊的子类可以新增一些成员,这里不再详述。
单件模式用途总结:确保某个类的对象的唯一性,常用来节省系统的资源,比如防止重复的数据库连接。
单件模式实现总结:收回所有新建对象的权利,把对象放入类的一个private成员中,仅提供一个对外的新建对象的方法,调用的时候判断对象是否已经新建。
单态模式用途总结:确保某个类所有的对象的成员都一致,同时允许灵活的继承这各类。但相对单件模式而言,系统资源开销要大一些。
单态模式实现总结:把所有相关的成员设置为static。