星际争霸允许玩家作弊,当然这是在人和电脑对战的时候。而且作弊有个特点,比如快速建造,能量无限是对所有的玩家(包括电脑)都生效,如果关闭了作弊,对所有的玩家的作用都同时消失。

这也就是说如果我们把作弊状态作为一个类,他只能有一个对象

待解决的问题:确保某个类只能有一个对象。

思路:把对外新建对象的权利都收回,包括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。