在我之前的question关于电子邮件服务,只有一个可变性,即 emailType
。现在我还有一个可变性,即传递给策略的可变性。它可以是 customerId
、orderId
或 cancellationId
,如下所示。
客户端不必传递所有参数。有些可以是 null
。例如,尽管 emailType
可以是 CancellationEmail
,但 cancellationId
可以为 null。
class EmailService
{
Send(int emailType, int? customerId, int? orderId, int? cancellationId = null)
{
switch(emailType)
{
case 1: SendSignupEmail(customerId);
break;
case 2: SendOrderEmail(customerId, orderId);
break;
case 3: SendCancellationEmail(orderId, cancellationId);
break;
}
}
SendSignupEmail(int? customerId);
SendOrderEmail(int? customerId, int? orderId = null);
SendCancellationEmail(int? orderId, int? cancellationId);
}
我看到的这个问题的解决方案是应用策略模式,但使用字典
。
interface ISendEmail
{
Send(dictionary allIds);
}
但这将强制客户端(调用 EmailService
的应用程序)创建 dictionary
。我可以将该字典创建移动到 Factory
方法。
如何通过应用 SOLID 原则更好地重构这段代码?
我愿意使用像 Unity 这样的容器来解决它,以消除一些手动对象构造。
最佳答案
我认为您错误地应用了 SOLID。您正在创建一个不能与相同意图互换的抽象。如果您为注册电子邮件创建了一个 ISendMail
实现,则无法将其取出并替换为发送订单电子邮件的实现。它采用不同的参数,更重要的是,功能意图不同。因此它应该需要不同的抽象。
我会创建以下抽象:
public interface ISignupEmailSender { void Send (int customerId); }
public interface IOrderEmailSender { void Send (int customerId, int orderId); }
public interface ICancellationEmailSender { void Send (int orderId, int cancellationId); }
为抽象添加实现,并在需要时注入(inject)它们。
现在,如果你想创建一个代理/服务来有一个发送所有电子邮件的地方,那么创建IEmailService
抽象,并注入(inject)上面的email-sender,并为每个添加一个相应的方法电子邮件发件人。就像您在当前的电子邮件发件人中使用的一样,但没有您当前使用的 void Send(int, int?, int?, int?)
方法。
对于具有不同幕后实现的不同抽象,使用具有多个参数的单一方法不会获得任何好处。它只会让事情变得复杂。保持简单。
关于c# - 使用设计模式重构多个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42808826/