点击上方“Lemon黄”关注我哦,不定期原创文,定期好技术文推广分享
确保一个类只有一个实例,并提供对其的全局访问入口。
如果你去一家诊所做检查,刚好诊所最近提供了免费药物。这个促销工作进展得非常顺利,前台人员的病人人数都超出他们的承受能力。每个人都很忙,以至于没有一个井井有条的等候室,这简直是一片混乱。接待员中的病人大量涌入后,安妮感到沮丧和压力,她走进诊所负责人的办公室,脱口而出:“我们需要组织病人,否则我们将不知所措”。
诊所的负责人召开会议,要求工作人员提出建议,然后他们想到了售票系统的想法。目的是使患者有条理的等候,以便减轻前台人员的人工登记工作。
让我们来看看我们能提供怎样的帮助。
在进行任何代码设计之前,我们需要了解诊所的状况和能力。该诊所只有一台物理打印机。
我们可以设计TicketPrinter
类,类似于以下定义的类:
class TicketPrinter
{
public $isPaperOut;
public function __construct()
{
$this->isPaperOut = true;
}
public function printTicket()
{
if ($this->isPaperOut) {
// 装在更多的纸张到打印机
$this->loadMorePapers();
$this->isPaperOut = false;
} else {
// 打印
$this->minusPaper();
echo 'print queue number';
}
}
}
每次执行打印作业时,printerTicket()
方法都必须检查纸张的状态。如果纸张用完,它将自动加载更多纸张(假设有可能)。
看来我们也需要检查墨水的状态。因此,我们还要添加如下:
class TicketPrinter {
public $isPaperOut;
public $isInkOut;
public function __construct()
{
$this->isPaperOut = true;
$this->isInkOut = true;
}
public function printTicket()
{
if ($this->isPaperOut) {
// 装在更多的纸张到打印机
$this->loadMorePapers();
$this->isPaperOut = false;
} else if($this->isInkOut ) {
// 添加墨水
$this->loadMoreInk();
$this->isInkOut = false;
} else {
// 打印
$this->minusPaper();
// 使用墨水
$this->deductInk();
echo 'print queue number';
}
}
}
看来我们有一个工作中的TicketPrinter
,但在继续之前,让我们再次检查一下情况。由于诊所中只有一台物理打印机,因此如果我们偶然创建了两个TicketPrinter
类实例,将会发生什么情况。因为他们使用的是同一台共享打印机,所以肯定会引起很大的问题。
您可能会争辩说,我们总是可以只创建另一个TicketPrinter
实例,但是如何确保每个人都遵循它呢?因此,我建议在这种情况下使用Singleton(单例)
模式。
我们来稍微修改下TicketPrinter
类:
class TicketPrinter
{
private static $uniqueInstance=null;
public $isPaperOut;
public $isInkOut;
private function __construct()
{
$this->isPaperOut = true;
$this->isInkOut = true;
}
public static function getInstance()
{
if (self::$uniqueInstance==null) {
self::$uniqueInstance = new TicketPrinter();
}
return self::$uniqueInstance;
}
public function printTicket()
{
}
}
由于TicketPrinte
r的构造函数(__construct()
)已变为私有,因此构造函数无法正常实例化它。为了获得TicketPrinter
的实例,我们改为:
$ticketPrinter = TicketPrinter::getInstance();
如你所见。单例模式(Singleton Pattern
)确保在整个系统的任何时候仅存在一个TicketPrinter
实例。