2011-01-06 38 views
1

我想确保我的应用程序强制执行依赖注入,但我进入有点咸菜......PHP OOP ::弄不清工厂类和传球对象构造

class Factory { 

public $sessionId; 
public $config; 
public $lib; 

function __construct() { 
    $this->getSessionId(); 
} 

function getSessionId() { 
    if (isset($_COOKIE['sk'])) { 
     $this->sessionId = trim($_COOKIE['sk']); 
    } else { 
     $sm = $this->createSessionManager(); 
     $this->sessionId = trim($sm->getNewKey()); 
     setcookie("sk", $this->sessionId, time() + 3600 * 3, "/"); 
     setcookie("vb", 0, 0, "/"); 
    } 

} 

function createBasket() { 
    $t = $this->createTicket(); 
    $co = $this->createContribution(); 
    $cfg = $this->createConfig(); 
    $basket = new Basket($t, $co, $cfg); 
    return $basket; 
} 

function createTicket() { 
    $sm = $this->createSessionManager(); 
    $cfg = $this->createConfig(); 
    $ticket = new Ticket($this->sessionId, $sm, $cfg); 
    return $ticket; 
} 

.. .. }

首先,我想知道我是否以正确的方式接近事情。一个例子浏览器画面 - 通过浏览器叫做 - 将是:

function __autoload($class_name) { 
    include 'classes/' . $class_name . '.class.php'; 
} 

$factory = new Factory; 

$performance = $factory->createPerformance(); 
$pno = (isset($_GET['pno']) ? $_GET['pno'] : 0); 
print $performance->displayHtmlListing($pno); 

我的其他问题/问题是有关我如何防止在对象A需要对象B,一个“抓22”的局面 - 在极少数情况下 - 将需要对象A 。

一个例子,在工厂类:

function createParser() { 
    $am = $this->createApiManager(); 
    $parser = new Parser($am); 
    return $parser; 
} 

解析器对象被传递对象插入的构造,以满足在业务逻辑它的依赖性。它的工作是读取文件请求,如果满足某些条件,它需要抓住$ am对象(APIManager)并发出对API的请求。问题是,APIManager通过解析器对象传递所有请求,并且我无法轻松地移除对解析器的依赖关系,而不会破坏业务规则或添加冗余条件代码。

想知道如果有人对如何解决这个问题有一些想法?

谢谢,詹姆斯

UPDATE:

的依赖问题

位的详细信息:

ApiManager.caller() - 它的工作是走下车来的API URL发送GET变量,检索结果。这个调用者()方法几乎被所有的类使用(也许这是一个很好的理由,因为它是超类,并扩展了需要它的类)。

调用方()的部分责任是检查正在进行的API调用。如果满足某个条件,则需要停止并调用SessionManager.getNewSession(),该SessionManager.getNewSession()将返回到相同的API并检索值。只有当这完成时,才能完成原始请求(在调用方()中)。

问题是SessionManager.getNewSession()也使用caller()。

回答

3

这只是恕我直言,但有大量名称包含“经理”,“上下文”,“解析器”等类的类是一种代码味道。我并不是说这些类肯定是错的 - 实际上每个应用程序都有它们。但是仔细想想 - 解析器是一件你拥有的东西,还是解析一个对象所做的事情?有没有一个真实世界的人与“API经理”的标题?他是否与会话管理员一起出去问问你关于你的TPS报告?等等

想想你的班级设计 - 我并不是说它是“错误的” - 因为我没有看到它,它无论如何都是主观的 - 但是你的班级是为真实世界的实体建模的,还是他们是在建模可以在实体上执行的行为吗?或者,更糟的是,他们是在建模某种任意的工作流程吗?你们的班级是否都有明确规定的责任,而不是试图做一些与他们无关的疯狂事情?

基本上,你遇到了这个问题,因为你的类设计并不是最优的。特别是,如果一个类的实例需要另一个类反之亦然的实例才能正常工作,你可能会重新考虑从你的设计中获益。

更新响应詹姆斯的更新

ApiManager.caller() - 它的工作是走下车来的API URL发送GET变量,并检索结果。

OOP的一个想法是,类表示实体(名词),方法表示动作(动词)。 ApiManager这里是一个实体(样一个抽象的,但我们会用它去),但caller()不是一个行动 - 即你不能“来电显示”的东西。你可以但是call()东西 - 我想在ApiManager的上下文中,这将“调用”API。我知道这只是两个小小的字母,但它对于ApiManager所做的事情的心理概念有很大的不同。

这个调用者()方法几乎被所有的类使用(也许这是一个很好的理由,因为它是超类,并扩展了需要它的类)。

继承最好用来支持多态,而不是代码共享 - 我不会那样做的......调用者()责任

部分是检查正在作出哪些API调用。如果满足某个条件,则需要停止并调用SessionManager.getNewSession(),该SessionManager.getNewSession()将返回到相同的API并检索值。只有当这完成时,才能完成原始请求(在调用方()中)。

一个问题是,caller()不应该有责任,因为它应该是一个动作(例如call()),而不是一个东西。行动不能承担责任。它应该做一些事情,最好是简单的事情。在与ApiManager的主意,因为这事,call()作为ApiManager做一个动作保持一致,这里是我怎么可能期望非常最低限度的示例的ApiManager工作:

class ApiManager { 

    private $session; 
    private $url; 

    // You'll probably need to set up the object differently; 
    // this is just an example.... 
    public function __construct($url) { 
     $this->setURL($url); 
    } 

    function call() { 
     if ($this->session is expired) { 
      // instead of calling SessionManager.getNewSession() here, 
      // why not just fold the session management functionality 
      // into ApiManager? They both use the same API, after all... 
      $session = $this->getNewSession(); 
     } 
     // do your call & return the response 
    } 

    public function setURL($url) { 
     $this->url = $url; 
    } 

    private function getNewSession() { 
     // get a new session 
     $this->session = $my_new_session; 
    } 

} 

你会发现,上面课程中的所有方法都是行为,他们都做了一些事情。锦上添花的是,不再需要担心SessionManager的依赖注入,因为它不再存在!毕竟,API会话确实只有ApiManager需要知道的东西,不是吗? :)

+0

>“如果一个类的实例,需要另一个类,反之亦然正常工作的实例” - 专题起动器使用依赖注入,其主要思想是将特定的类实例注入依赖类 – galymzhan 2011-01-06 18:39:03