3

我有一个关于应用 GRASP 控制器模式同时保持其 SOLID 的问题,更具体地说,同时保持它的单一职责。

维基百科的控制器模式定义说:

控制器模式将处理系统事件的责任分配给代表整个系统或用例场景的非 UI 类。控制器对象是负责接收或处理系统事件的非用户界面对象。

关于 SOLID 的单一责任原则

在面向对象编程中,单一职责原则指出每个类都应该有单一职责,并且该职责应该完全由类封装。它的所有服务都应与该责任密切相关。

让我们来看一些示例代码。假设我有以下 Java 类:

public class foo {
    public foo(){}
    public int foo1(){/*Some code*/}
    public String foo2(){/*Some code*/}
    public String foo3(int foo31){/*Some code*/}
}

public class bar {
    public bar(){}
    public int bar1(){/*Some code*/}
    public String bar2(){/*Some code*/}
    public String bar3(int bar31){/*Some code*/}
}

什么是一个好的控制器实现,同时保持一个单一的责任?我只是通过用例还是什么?例如:

public class bazController {

    private foo fooInstance;
    private bar barInstance;

    public bazController(){
        this.fooInstance = new foo();
        this.barInstance = new bar();
    }

    public void fooAction1(int arg){
        this.foo.foo3(arg);
    }

    public void barAction1(int arg){
        this.bar.bar3(arg);
    }

    public void fooAction2(){
        this.foo.foo1();
    }

    public void barAction2(){
        this.bar.bar1();
    }

}

我在这里承担一项责任吗?我这样做或理解正确吗?事先谢谢你。

编辑:如果bazController有这种方法会发生什么,使两个类相关?

public int bazAction(){
    return this.foo.fooAction1() + this.bar.barAction1();
}
4

2 回答 2

2

我不是一个经验丰富的开发人员,但我会尝试基于对概念的理解来探索我的想法。

单一职责:我相信,这是“你的班级负责什么?”这个问题的答案。当你要回答这个问题时,你应该只说一个责任。在您的情况下,答案是:“我的班级负责控制 baz”(您的实现当然应该这样做)。

由于您的答案仅指定了一项职责,因此您正确实施了它。

但我认为您的代码不符合D. SOLID即依赖注入。您可以通过构造函数或其他方式注入foo和注入。bar

更新:您的班级仍然很好,因为您班级的职责是control the baz.

foo并且bar是 的组件,baz您正在通过bazCntroller.

我可以说,Single Responsibility当您添加的方法除了控制您的 baz 之外,您还违反了其他工作。前任:

public void LogBazExecution() {}
public int GetBazExecutionCount() {}

如您所见,baz controller跟踪 baz 动作触发的次数不是 的责任。

原理背后的原因是ease of maintenance。当每个类被设计为只有一个职责时,您很容易在系统中找到故障的位置,并且可以在需要时轻松扩展它,而不会引入很多新的错误。

于 2013-02-01T04:54:06.683 回答
1

这实际上取决于类foobar背后的上下文以及它们在业务方面与控制器的业务上下文的紧密程度。

在您的示例中,您有与foo和 一起使用的方法bar,但与和一起使用的方法为零。对我来说,这表明并且可能没有太多共同点。foobarfoobar

这就是我将如何更改您的示例:(假设foo并且bar没有任何共同点):

public class fooController
{
    private foo fooInstance;

    public fooController() {
        fooInstance = new foo
    }

    public void fooAction1(int arg){
        this.foo.foo3(arg);
    }

    public void fooAction2(){
        this.foo.foo1();
    }
}

public class barController 
{

    private bar barInstance;

    public bazController(){
        this.barInstance = new bar();
    }

    public void barAction1(int arg){
         this.bar.bar3(arg);
    }

    public void barAction2(){
         this.bar.bar1();
    }
}

编辑
您将拥有一个委托给多个业务逻辑实例的控制器的示例可能如下所示:

public class UserSettingsController
{
    private UserAddressLogic addressLogic;
    private UserPersonalInfoLogic personalInfoLogic;

    public UserSettingsController() {
        addressLogic = new UserAddressLogic();
        personalInfoLogic = new UserPersonalInfoLogic();
    }

    public User GetUser() {
        User user = new User();
        user.Address = addressLogic.GetUserAddress();
        user.PersonalInfo = personalInfoLogic.GetPersonalInfo();

        return user;
    }
}
于 2013-02-01T04:45:58.700 回答