我有一个关于应用 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();
}
我不是一个经验丰富的开发人员,但我会尝试根据对概念的理解来探索我的想法。
单一责任:我相信,这是"你的班级负责什么?"这个问题的答案,当你要回答这个问题时,你应该只告诉一个责任。在你的例子中,答案是:"我的类负责控制baz"(当然,你的实现应该这样做)。
由于您的答案仅指定了一项责任,因此您正确地实施了它。
但我认为您的代码不符合SOLID
D
,即依赖注入。您可以通过构造函数或其他方式注入foo
和bar
。
更新:你的班级仍然很好,因为你的班级的责任是control the baz
。
foo
和bar
是baz
的组成部分,您通过bazCntroller
控制它们的行动。
我可以说,当您添加的方法执行除控制 baz 之外的其他工作时,您违反了Single Responsibility
。前任:
public void LogBazExecution() {}
public int GetBazExecutionCount() {}
如您所见,baz controller
没有责任跟踪 baz 操作触发了多少次。
原理背后的原因是ease of maintenance
。当每个类被设计为只有一个职责时,你可以很容易地在系统中找到故障的位置,并在需要时轻松扩展它,而不会引入太多新的错误。
这实际上取决于类 foo 和 bar 背后的上下文,以及它们与控制器的业务上下文在业务方面的紧密结合程度。
在您的示例中,您有适用于foo
的方法和适用于bar
的方法,但零个同时适用于foo
和bar
的方法。对我来说,这表明foo
和bar
可能没有太多共同点。
这就是我将如何更改您的示例:(假设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;
}
}