SRP真的让我烦恼。我知道如何找到责任我不知道如何正确组装它们 e.g
class Modem{
public void dial(){//code here}
public void hangup(){//code here}
public void send(){//code here}
public void recive(){//code here}
}
在这个常见的例子中,我们有连接和沟通的责任。所以我们把它分成2个新接口
interface Connection{
public void dial();
public void hangup();
}
interface Communication{
public void send();
public void recive();
}
实施它们:
class SimpleModemConnection implements Connection{
public void dial(){//code here}
public void hangup(){//code here}
}
class SimpleModemCommunication implements Communication{
public void send(){//code here}
public void recive(){//code here}
}
此时我真的不知道客户端代码应该是什么样子
我是否将这些接口聚合到Modem类中?
class Modem {
Connection connection = new SimpleModemConnection();
Communication communication = new SimpleModemCommunication();
}
main(){
Modem modem = new Modem();
modem.connection.dial();
modem.communication.send();
modem.communication.recive();
modem.connection.hangup();
}
我是否直接使用它们
main(){
Connection connection = new SimpleModemConnection();
Communication communication = new SimpleModemCommunication();
connection.dial();
communication.send();
communication.recive();
connection.hangup();
}
或者还有其他方法吗?
答案 0 :(得分:1)
恐怕你可能会过度思考这个问题。调制解调器需要连接和通信。除非你知道并期望这两者可以分开的情况,否则就没有必要将它分开。最后,这些原则不应成为您设计的主要推动力。这应该是您对域的了解以及您期望在系统中进行的更改。
那么您需要回答的是,您的调制解调器类是否需要更换其连接/通信子系统?
答案 1 :(得分:0)
有时这可能会让人感到困惑。我每天都在努力解决同样的问题,但你想一想就好了。我一直在积极寻求使用SOLID原则以及我的TDD实践。您似乎没有想到的一件事是谁将在代码中使用您的调制解调器,单元测试和实际对象用户。
在我看来,它就是这样的。调制解调器负责拨号,挂断,发送和接收数据,因此这些是向您的API用户公开的功能(接收除外),无论是您的单元测试还是您的代码用户。因此,存在以下内容。
<强> IModem.cs 强>
interface IModem
{
public bool Connect(); // Seen in your code as dial
public void Disconnect(); // Seen in your code as hangup
public void SendData(); // Take data as parameter
// Receive will not be public, instead I would make it call out to the user saying "I have received data for you"
}
这清楚地表明调制解调器对象的责任是将数据连接,断开连接并发送到需要的位置。现在调制解调器是否进行连接和通信是另一个问题。我会说你使用SimpleConnection和SimpleCommunication模块的东西是完美的(我会稍微改变命名;))。连接变为IConnectionModule,通信变为ICommunicationModule,以及一些功能名称更改。拨号连接,挂断到断开连接并发送到SendData。考虑到这一点,我采取以下方法。
我的调制解调器的责任:我的调制解调器将使用它拥有的模块将用户连接到远程主机,以及断开与主机的连接或发送任何数据必要。 然后上面的定义产生以下代码。
<强> Modem.cs 强>
class Modem : IModem
{
private IConnectionModule _connectionModule;
private ICommunicationModule _communicationModule;
public Modem(IConnectionModule connectionModule, ICommunicationModule communicationModule)
{
_connectionModule = connectionModule;
_communicationModule = communicationModule;
}
public bool Connect()
{
bool connectionSuccess = _connectionModule.Connect()
return connectionSuccess;
}
public void Disconnect()
{
_connectionModule.Disconnect();
}
public void SendData()
{
_communicationModule.SendData();
}
}
考虑上述情况,您可以按如下方式列出职责:
调制解调器:用作API用户之间的桥梁,允许用户发送和接收信息。
连接模块:将调制解调器连接到主机(用户永远不会使用它,唯一的用户就是它的单元测试套件和调制解调器)
通讯模块:向已连接的主机发送信息(用户永远不会使用此功能,唯一使用此功能的用户将是它的单元测试套件和调制解调器)
将模块“隐藏”给用户的原因是调制解调器的用户不必知道正在使用哪个连接模块。您所要做的就是调用Connect / Disconnect,并提供功能。其余的都应该是“看不见的”。同样,这完全取决于您的开发风格,但我总是尽量保持良好的分离,并确保每次调用始终有一个动作。无论是养殖到不同的对象还是在课堂内完成。
我希望这有帮助,让我知道你的想法,我总是在讨论设计和SOLID原则。