这就是界面设计的目的。首先定义一个通用接口:
public interface INotifier
{
bool Notify();
}
其次,将其实施到您的objX
课程:
public class obj1 : INotifier
{
public int Id { get; set; }
public string Name { get; set; }
public bool Notify()
{
var sender = new SendSMS();
return sender.Send(this);
}
}
public class obj2 : INotifier
{
public int AccNum { get; set; }
public string Name { get; set; }
public bool Notify()
{
var sender = new SendPush();
return sender.Send(this);
}
}
public class obj3 : INotifier
{
public string Email { get; set; }
public string Phone { get; set; }
public bool Notify()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
最后,更改通知方法以接受接口类型作为参数:
public class NotificationHelper : INotificationHelper
{
public bool SendNotification(INotifier obj)
{
return obj.Notify();
}
}
编辑(2019):
我正在重新审视这个答案,因为它似乎得到了相当多的关注。 OP 可能早已继续前进,但对于其他可能偶然发现这个答案的人来说,这是另一个解决方案。
我仍然相信接口是正确的出路。然而,上面建议的接口非常通用,最终并不是很有用。它还遇到了一些 DRY 违规,因为正如 Fabio 在评论中所说,如果两个objX
类以相同的方式实现通知,这种方法迫使您在它们之间复制代码。
不是一个全局接口,而是为每个特定通知任务提供接口,即ISMSNotification
, IPushNotification
, IEmailNotification
。然后,您可以使用 mixin 模式为每个接口实例提供 send 方法的默认实现:
interface ISmsNotifier
{
int SmsId { get; }
string SmsName { get; }
}
static class ISmsNotifierExtensions
{
public static bool NotifySms(this ISmsNotifier obj)
{
var sender = new SendSMS();
return sender.Send(obj);
}
}
// ---------------------------------------------
interface IPushNotifier
{
int PushAccNum { get; }
string PushName { get; }
}
static class IPushNotifierExtensions
{
public static bool NotifyPush(this IPushNotifier obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
// ---------------------------------------------
interface IEmailNotifier
{
string EmailAddress { get; }
string EmailPhone { get; }
}
static class IEmailNotifierExtensions
{
public static bool NotifyEmail(this IEmailNotifier obj)
{
var sender = new SendEmail();
return sender.Send(obj);
}
}
然后您可以在objX
像这样的类:
public class obj1 : INotifier, ISmsNotifier
{
public int SmsId { get; set; }
public string SmsName { get; set; }
public bool Notify() => this.NotifySms();
}
public class obj2 : INotifier, IPushNotifier
{
public int PushAccNum { get; set; }
public string PushName { get; set; }
public bool Notify() => this.NotifyPush();
}
public class obj3 : INotifier, IEmailNotifier
{
public string EmailAddress { get; set; }
public string EmailPhone { get; set; }
public bool Notify() => this.NotifyEmail();
}
请注意,使用这种方法不仅可以轻松支持使用相同通知系统的对象,还可以支持具有以下功能的对象:multiple通知系统:
public class obj4 : INotifier, IEmailNotifier, IPushNotifier
{
public int PushAccNum { get; set; }
public string PushName { get; set; }
public string EmailAddress { get; set; }
public string EmailPhone { get; set; }
public bool Notify() => this.NotifyEmail() && this.NotifyPush();
}
您可能会注意到这种方法使得NotificationHelper
已过时,因为不再需要通过处理步骤传递对象来确定通过哪个通知系统处理对象。这是真的,也许也是正确的,因为对象应该完全能够自己决定这一点(取决于你处理这个问题的心态)。然而,NotificationHelper
可能仍然有其用途,例如,如果您想要预处理发送到通知服务的信息,或者如果您想要一个公共入口点来帮助模拟和测试。
C#8 注意:
C# 8 的一项拟议功能是能够为接口提供接口定义本身内方法的默认实现。当(如果)发生这种情况时,您不需要再使用 mixin 模式,并且可以直接在接口中定义默认方法实现。该功能尚未最终确定,但它可能看起来像这样:
interface ISmsNotifier
{
int SmsId { get; }
string SmsName { get; }
public bool NotifySms()
{
var sender = new SendSMS();
return sender.Send(this);
}
}
// ---------------------------------------------
interface IPushNotifier
{
int PushAccNum { get; }
string PushName { get; }
public bool NotifyPush()
{
var sender = new SendEmail();
return sender.Send(this);
}
}
// ---------------------------------------------
interface IEmailNotifier
{
string EmailAddress { get; }
string EmailPhone { get; }
public bool NotifyEmail()
{
var sender = new SendEmail();
return sender.Send(this);
}
}