设计问题:哪种做法更好? (第2部分)

时间:2010-01-12 09:58:06

标签: php design-patterns

我有一个Web界面,我将从中收集用户数据(用户名,密码,电子邮件等),后端必须将这些数据提供给其他3个系统(SystemA,SystemB,SystemC)。

供应由3个不同的API完成,每个系统对应一个系统(A,B和C)。

我在后端的当前设计看起来像这样:


interface ProvisionData
{
    public function createUser();
    public function deleteUser();
    public function changePassword();
}


class SystemA_API_wrapper implements ProvisionData
{
    public function createUser(){ ... }
    public function deleteUser(){ ... }
    public function changePassword(){ ... }
}

class SystemB_API_wrapper implements ProvisionData { public function createUser(){ ... } public function deleteUser(){ ... } public function changePassword(){ ... } }

class SystemC_API_wrapper implements ProvisionData { public function createUser(){ ... } public function deleteUser(){ ... } public function changePassword(){ ... } }

每个System * _API_wrapper都有不同的createUser()(和其余)函数的实现。

在前端,我创建了一种代理类,我使用从Web界面收集的数据来提供它。它看起来像:


class provisionProxy
{
    public $sA = null;
    public $sB = null;
    public $sC = null;

//constructor instantiates all System*_API_wrapper objects
public function __construct() {        
     $sA = new SystemA_API_wrapper();
     $sB = new SystemB_API_wrapper();
     $sC = new SystemC_API_wrapper();
}

// proxy function deleteUser calls deleteUser() of each of 
// our APIs 
public function deleteUser($username, $password) {
     $this->sA->deleteUser($username, $password);         
     $this->sB->deleteUser($username, $password);
     $this->sC->deleteUser($username, $password);
}

}

有没有人有任何建议或更好的做法?

(我已经发布了相同的问题,但由于技术问题,我无法登录到我的旧帐户,所以问题会在我的新帐户下修改并重新发布。原始问题可在此处找到:{{3 } - 谢谢)

3 个答案:

答案 0 :(得分:3)

基于您无法将三个后端系统更改为全部访问用户管理的中央系统(这会更好)的假设,我建议的唯一更改是您的代理,您需要在其中进行硬编码调用对于您的三个系统中的每一个 - 最好在构造函数中创建ProvisionData对象列表,然后在删除/创建调用中,循环遍历该列表并在每个系统上调用相应的方法。

这意味着,如果在将来的某个时刻,您必须将系统D添加到此,那么可以通过在单个位置进行更改来完成。

(我的PHP技能有点粗糙,因此不会尝试提供代码)。

答案 1 :(得分:1)

设计看起来不错,但是如果你想从抽象中获得任何好处,那么将所有ProvisionData对象添加到Paddy建议的列表中是绝对必要的。即使三个外部系统是固定的并且永远不会改变,这也适用。此外,将要执行的operation与执行它的对象(又名Command pattern)分开将使事务支持和撤消行为成为可能。

考虑这个例子 - 由于您需要在所有系统中保持数据的一致性,因此我会猜测会涉及某种交易。如果有createUser()操作且一个系统关闭,您不希望在其他两个系统上创建用户,因此从代理的角度来看,整个操作都会失败。在列表中处理这些操作比单独检查每个项目更容易。使用列表,伪代码:

/*
 * systems object represents a list of systems
 * execute() and undo() are methods in the systems object
 * 
 * result represents the result of performing an operation on some systems
 * successfulSystems represents systems in which the operation was successful
 */
operation = new Operation("createUser", ["param 1", "param 2", ..])
result = systems.execute(operation);
// if operation failed in any of the systems
if(result.FAILURE) {
    // then undo the operation on systems where it did succeed
    result.successfulSystems.undo(operation);
}

列表基本上允许将外部子系统整体分组,从而为自己添加另一级抽象,allany等操作比单独检查更有意义。分离操作会带来更多好处。

答案 2 :(得分:0)

您可以使用Observer模式使后端系统可以独立于其编号处理您的前端数据,这可能会发生变化。