【发布时间】:2014-09-29 13:54:12
【问题描述】:
我有一个关于 OOP 和接口的奇怪问题,在尝试寻找最佳设计时让我一头雾水。
有两个不同的类在不同的环境中进行相同的工作(例如发送消息)。这两种环境使用不同的参数来定义接收者;一种是使用邮件地址,另一种是使用用户名。 所以这两个类都有相同但略有不同的消息发送方法。
MessageSenderViaMailManager.cs
public bool SendMessage(string recipientMailAddress, string message) {
..
}
MessageSenderViaUsernameManager.cs
public bool SendMessage(string recipientUserName, string message) {
..
}
两个类中还有其他类似的方法,负责相同的工作,但可能需要不同的参数。 为了使这些具有界面的管理器可用,我创建了一个名称为 IMessageSenderManager 并包含这样的定义的管理器。
public bool SendMessage(string recipientUserName, string recipientMailAddress, string message);
因此,我的课程中的两个 SendMessage 方法都更改为:
public bool SendMessage(string recipientUserName,string recipientMailAddress, string message) {
..
}
使用这个新的 SendMessage 方法,我可以使用适当的参数作为收件人(邮件地址或用户名)。这看起来不错,但实施看起来很奇怪。因为我必须发送所有参数,而不知道在编码时将在运行时使用哪个参数。例如:
// Sending message via username implementation
string userName = GetUserNameFromSomeWhere();
string mailAddress = GetUserMailFromSomeWhere();
IMessageSenderManager manager = MessageSenderFactory();
manager.SendManager(userName, mailAddress, "This messaged sent by your user name");
和上面的代码一样,通过邮件地址发送消息看起来很相似。
在我看来,这不是一个好的设计,所以我开始考虑更好的解决方案。因为如果我想实现另一个 MessageSender 提供者,它使用不同的接收者描述符,我必须向我的接口添加另一个参数,所以对所有类。 我想,我可以用一个通用收件人参数更改两个收件人参数,并为上下文发送适当的值。但我试图在动态环境中使用它,并且方式(通过用户名或邮件)将在运行时确定,所以我不能使用它。
我打算制作一个灵活的库,可以解耦使用或对其他开发人员友好地进行单元测试,我不想将它们与无意义的参数或糟糕的设计混淆。
对于这种情况,有没有更好的设计?
编辑:
实际上是我的错误,我忘记了我的问题中非常重要的部分,对此我深表歉意。 正如您从答案中看到的那样,有一些替代方法可以解决我上面描述的第一个问题。但是之后? 我在代码中提到,接口是从 MessageSenderFactory() 方法返回的,但我不知道返回的是哪个消息发送管理器。所以我有两个选择,
- 编写 if 条件以检查从方法返回的管理器,并为该管理器发送具有适当值的强制参数,并将其他参数发送为空。
- 无论经理是谁,都发送具有正确值的所有参数,因此它们都可以正常工作。但将来,如果添加了另一个经理,我每次都需要为该经理发送额外的参数。
- 还有其他我想不到的方法吗?
除了 SendMessage 之外的其他方法可能需要根据管理器的不同参数,这在运行时是未知的。例如:
MessageSenderViaMailManager 的 AddContact 方法可能需要以下参数:
- 联系人姓名
- 联系邮箱
- 联系电话
- 联系邮件类型(丰富、普通)
或MessageSenderViaUserNameManager的AddContact方法可能需要以下参数:
- 联系人姓名
- 联系邮箱
- 联系人用户名
- 联系消息平台(Twitter、facebook、vs)
- 联系人发件人姓名
所以这让一切变得非常复杂。 我的 IMessageSenderManger 的 AddMethod 应该如何?它应该包含所有参数吗?我应该超载吗?或者我应该将公共参数放在方法中,并使其他参数因经理而异(如 MVC 中的 HtmlHelper)
我知道这个问题不是很扎实,而且我不擅长用英语描述。
GitHub 编辑:
我创建了一个小例子并上传到github,我希望这可以帮助我更好地解释我的问题 https://github.com/bahadirarslan/InterfaceDesign
【问题讨论】:
-
将
User对象传递给SendMessage方法怎么样? -
SendMessage的实现如何? -
对于初学者来说,既然你问“什么是最好的”,你的问题是“基于意见的”,所以我投票结束,我没有添加答案。此外,这是一个非常本地化的问题,它对未来的读者几乎没有帮助,因为即使是标题也太模糊,无法帮助任何人通过搜索查询甚至谷歌找到它。这就是近距离投票的原因。不过,我可以看到你的问题,我会尝试在 cmets 中回复。
-
@quetzalcoatl 我不同意,这是如何基于意见的? OP 在这里有一个特定的问题要解决。虽然我同意这个问题的标题写得不好,如果改变的话。它肯定会对未来的读者有所帮助。
-
实际上,我只是注意到我想写的所有内容都可以压缩为 KlausByskovPedersen 已经说过的内容:更改
string email/string username以便 SendMessage 将User对象作为目标,并且底层的 SendMessage 实现将能够从 User 对象中选择它需要的任何内容。如果您没有 User 之类的东西,请传递 UserID(假设您的用户有它)..