Setting Sun's Blog – 残阳 彪悍的人生不需要解释~~

21二/100

使用Locator获取对象实例

一个高效、易懂、便于管理的加载方法,在开发过程中会方便不少。 下面我来说一个比较简单的方法。 首先我们创建一个抽象类LocatorAbs.php

abstract class LocatorAbs
{
	/**
	 * 初始化的对象
	 *
	 * @var array
	 */
	private $_objects = array();

	/**
	 * 魔术方法实现getXXX得到对象
	 *
	 * @param string $name
	 * @param array $arguments
	 * @return object
	 */
	public function __call($name, $arguments)
	{
		$pos = strpos($name, 'get');

		if($pos === false)
		{
			throw new Exception('invalid class name of ' . $name);
		}

		$className = substr($name, 3);
		return $this->get($className);
	}

	/**
	 * 根据一个传入的类名取得实例
	 *
	 * @param string $className
	 * @return object
	 */
	protected function get($className)
	{
		if(array_key_exists($className, $this->_objects))
		{
			return $this->_objects[$className];
		}

		$object = new $className();
		$this->_objects[$className] = $object;

		return $object;
	}
}

这是我们写了一个魔术方法和一个get方法
get方法是用来得到实例对象的,均采用单例模式来实例
魔术方法我们一会才会用到,先不说了。

随后我们创建一个ServiceLocator用来管理我们的业务实例

require_once ROOT_PATH . DIRECTORY_SEPARATOR . 'LocatorAbs.php';
class ServiceLocator extends LocatorAbs
{
	private static $instance;
	private function __construct()
	{}

	/**
	 * 得到ServiceLocator对象实例
	 *
	 * @return ServiceLocator
	 */
	public static function getInstance()
	{
		if(!self::$instance)
		{
			self::$instance = new ServiceLocator();
		}

		return self::$instance;
	}

	/**
	 * 根据一个类名取得一个实例对象
	 *
	 * @param string $className
	 * @return object
	 */
	protected function get($className)
	{
		require_once SERVICE_PATH . DIRECTORY_SEPARATOR . $className . '.php';
		return parent::get($className);
	}

	/**
	 * 取得NiubilityService对象实例
	 *
	 * @return NiubilityService
	 */
	public function getNiubilityService()
	{
		return $this->get('NiubilityService');
	}
}

我们把构造方法私有化,使之不能实例,采用单例模式来实例,是为了确保LocatorAbs中的objects不会丢失
在ServiceLocator中我们有一个方法getNiubilityService,其实可以不用写(因为在LocatorAbs中有个魔术方法可以自动帮助我们做这些事情),但是为了IDE联想忍了。

下面我们来创建两个业务文件
NiubilityService.php

class NiubilityService
{
	public function __construct()
	{}

	public function aa()
	{
		echo "哥的博客 http://www.setting.cc/blog\n";
	}
}

TestService.php

class TestService
{
	/**
	 * ServiceLocator对象实例
	 *
	 * @var ServiceLocator
	 */
	private $serviceLocator;

	public function __construct()
	{
		$this->serviceLocator = ServiceLocator::getInstance();
	}

	public function test()
	{
		echo '感受哥体内的和谐之力吧,P民的世界与哥何干~';
		echo "\n------------华丽的分割线------------\n";

		$niubilityService = $this->serviceLocator->getNiubilityService();
		$niubilityService->aa();
	}
}

现在准备工作已经完成,让我们来看看他是怎么工作的吧!!!

test.php

define(ROOT_PATH, realpath('.'));
define(SERVICE_PATH, realpath('.'));

require_once ROOT_PATH . DIRECTORY_SEPARATOR . 'ServiceLocator.php';

$serviceLocator = ServiceLocator::getInstance();

$niubilityService = $serviceLocator->getNiubilityService();
$niubilityService->aa();

$testService = $serviceLocator->getTestService();
$testService->test();

打印结果如下:

哥的博客 http://www.setting.cc/blog
感受哥体内的和谐之力吧,P民的世界与哥何干~
------------华丽的分割线------------
哥的博客 http://www.setting.cc/blog

我们可以看到,他轻松的完成了各各业务之间的那啥。

$testService由于没有在ServiceLocator中写getTestService方法,所以IDE没有相关的联想

哥刚看完 《看你妹之XXXX》感触颇深,怕被和谐,全名我就不写了。哦一西吧!!!!!