深入PHP面向对象、模式与实践——生成对象(1)

单例模式

  • 生成对象的问题和解决方案
abstract class Employee
{
    protected $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    abstract function fire();
}

class Minion extends Employee
{
    function fire()
    {
        print "{$this->name}:I'll clear my desk\n";
    }
}

class NastyBoss
{
    private $employees = array();

    function addEmployee($employeeName)
    {
        $this->employees[] = new Minion($employeeName);
    }

    function projectFail()
    {
        if (count($this->employees) > 0) {
            $emp = array_pop($this->employees);
            $emp->fire();
        }
    }
}

$boss = new NastyBoss();
$boss->addEmployee("harry");
$boss->addEmployee("bob");
$boss->addEmployee("mary");
$boss->projectFail();

由于在NastyBoss类中直接实例化Minion对象,代码的灵活性受到限制。如果NastyBoss对象可以使用Employee类的任何实例,那么代码在运行时就能应对更多特殊的Employee。如下类图:

这里写图片描述

如果NastyBoss类不实例化Minion对象,那么Minion对象从何而来?在方法声明中限制参数类型来巧妙避开这个问题,然后除了在测试时实例化对象,在其他时候尽量避免提及。

如果是这里存在一个原则的话,那便是“把对象实例化的工作委托出来”。我们可以委托一个独立的类或方法来生成Employee对象。

abstract class Employee
{
    protected $name;
    private static $types = array("minion", 'clueup', 'wellconnected');

    static function recruit($name)
    {
        $num = rand(1, count(self::$types)) - 1;
        $class = self::$types[$num];
        return new $class($name);
    }

    public function __construct($name)
    {
        $this->name = $name;
    }

    abstract function fire();
}

class wellConnected extends Employee
{
    function fire()
    {
        print "{$this->name}: i'll call my dad\n";
    }
}

$boss = new NastyBoss();
$boss->addEmployee(Employee::recruit("harry"));
$boss->addEmployee(Employee::recruit("bob"));
$boss->addEmployee(Employee::recruit("mary"));
  • 单例模式

经过良好设计的系统一般通过方法调用来传递对象实例。每个类都会与背景环境保持独立,并通过清晰的通信方式来与系统中其他部分进行协作。有时你需要使用一些作为对象间沟通渠道的类,此时就不得不引入依赖关系。

下面创建一个无法从自身外部来创建实例的类:

class Preferences
{
    private $props = array();
    private static $instance;

    private function __construct()
    {
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new Preferences();
        }
        return self::$instance;
    }

    public function setProperty($key, $val)
    {
        $this->props[$key] = $val;
    }

    public function getProperty($key)
    {
        return $this->props[$key];
    }
}

$pref = Preferences::getInstance();
$pref->setProperty("name", "matt");

unset($pref);

$pref2 = Preferences::getInstance();
print $pref2->getProperty("name") . "\n";

这里写图片描述

使用单例模式和使用全局变量都可能被误用,适度地使用单例模式可以改进系统设计。在系统中传递那些不必要的对象令人厌烦,而单例模式可以让你从中解脱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值