hea*_*ath 6 php design-patterns factory-pattern
使用php 5.2,我正在尝试使用工厂将服务返回给控制器.我的请求uri的格式为www.mydomain.com/service/method/param1/param2/etc.然后我的控制器将使用uri中发送的令牌调用服务工厂.从我所看到的情况来看,我的工厂有两条主要路线可供选择.
单一方法:
class ServiceFactory {
public static function getInstance($token) {
switch($token) {
case 'location':
return new StaticPageTemplateService('location');
break;
case 'product':
return new DynamicPageTemplateService('product');
break;
case 'user'
return new UserService();
break;
default:
return new StaticPageTemplateService($token);
}
}
}
Run Code Online (Sandbox Code Playgroud)
或多种方法:
class ServiceFactory {
public static function getLocationService() {
return new StaticPageTemplateService('location');
}
public static function getProductService() {
return new DynamicPageTemplateService('product');
}
public static function getUserService() {
return new UserService();
}
public static function getDefaultService($token) {
return new StaticPageTemplateService($token);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,考虑到这一点,我将有一些通用服务,我将传递该令牌(例如,StaticPageTemplateService和DynamicPageTemplateService),它可能会实现另一个工厂方法,就像这样来获取模板,域对象等等.将是特定服务(例如,UserService),它将是该令牌的1:1而不会被重用.因此,对于少量服务而言,这似乎是一种不错的方法(如果不是,请提供建议).但是,随着时间的推移,随着时间的推移和我的网站的增长,我最终会有100种可能性.这似乎不再是一个好方法.我只是开始使用或者是否有其他更适合的设计模式?谢谢.
更新:@JSprang - 令牌实际上是在uri中发送的,例如mydomain.com/location需要特定于loction的服务,而mydomain.com/news需要特定于新闻的服务.现在,对于其中很多,这项服务将是通用的.例如,许多页面将调用StaticTemplatePageService,其中令牌被传递到服务.反过来,该服务将获取"位置"模板或"链接"模板,然后将其吐出.有些人需要传递令牌的DynamicTemplatePageService,例如"news",该服务将获取一个NewsDomainObject,确定如何呈现它并将其吐出.其他人,比如"user"将特定于UserService,其中它将具有Login,Logout等方法.因此,基本上,令牌将用于确定需要哪个服务,如果它是通用服务,则该令牌将是传递给那项服务.也许令牌不是正确的术语,但我希望你能达到目的.
我想使用工厂,所以我可以轻松换掉我需要的服务,以防我的需求发生变化.我只是担心,在网站变得更大(页面和功能)后,工厂将变得相当臃肿.但我开始觉得我无法摆脱将数组存储在数组中(如Stephen的解决方案).这对我来说并不感觉OOP,我希望能找到更优雅的东西.
这是我如何创建一个单例工厂(为简洁起见,删除了注释):
class ServiceFactory {
private static $instance;
private function __construct() {
// private constructor
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public static function init() {
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function get_service($name, $parameter) {
$name .= 'TemplateService';
return $this->make_service($name, $parameter);
}
private function make_service($name, $parameter) {
if (class_exists($name)) {
return new $name($parameter);
} else {
throw new LogicException('Could not create requested service');
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在最简单的形式中,只需传递服务的字符串名称:
function whatever() {
$ServiceFactory = ServiceFactory::init();
$new_service = $ServiceFactory->get_service('StaticPage', 'location');
return $new_service;
}
Run Code Online (Sandbox Code Playgroud)