1

我有一个要求,用户需要配置他们希望在发生错误时收到警报的方式。他们拥有的选项如下:

1.) 在事件日志中创建一个事件

2.) 将电子邮件发送到从用户界面指定的电子邮件

我目前使用的类使用以下接口

interface INotificationSender
{
   virtual void SendMessage(string message);
}

我的接口将由以下 2 个具体类实现

class EmailerNotificationSender: public INotificationSender
{
   string m_EmailAddress;

   public EmailerNotificationSender(string emailAddress)
   {
       m_EmailAddress = emailAddress;
   }
   public virtual void SendMessage(string Message)
   {
      // Send Message to email specified in member variable
   }
} 


class EventLogNotificationSender: public INotificationSender
{
   public virtual void SendMessage(string Message)
   {
      // Log message in event log using
   }

}

我当前的界面代码如下所示

public class MyUserinterfaceWindow
{
    private INotificationSender m_NotificationSender; // concrete type depends on user interface selection!

    public void Button_Click(...)
    {
       if (emailSelected)
       {
           m_NotificationSender = new EmailerNotificationSender(textbox.email)
           return;
       }
        m_NotificationSender = new EventLogNotificationSender();
    }

    public void SendAlert()
    {
        m_NotificationSender.SendMessaged("SOMETHING BAD HAPPENED");
    }
}

摘要/问题: 我如何删除正在实例化的具体类型的存在(例如 EventLogNotificationSender 和 EmailerNotificationSender )

注意: EventLogNotificationSender 的具体构造函数不需要参数,而 EmailNotificationSender 的具体构造函数需要一个字符串参数!

4

1 回答 1

0

隐藏复合 INotificationSender实现背后的两个实现。

如果您可以延迟用户选择他想要记录的源,您可以将该选择逻辑移动到组合中,这样可以防止该逻辑使MyUserinterfaceWindow. 这是一个例子:

public class CompositeNotificationSender : INotificationSender {
    private readonly EmailerNotificationSender mailer;
    private readonly EventLogNotificationSender eventLogger;

    public CompositeNotificationSender(
        EmailerNotificationSender mailer,
        EventLogNotificationSender eventLogger) {
        this.mailer = mailer;
        this.eventLogger = eventLogger;
    }

    public virtual void SendMessage(string Message) {
        bool logToMail = AskUserWhereToLog();
        var logger = logToMail ? this.mailer : this.eventLogger;
        logger.SendMessage(Message);
    }

    private bool AskUserWhereToLog() {
        // TODO:
    }
}

由于此类询问用户,因此与 UI 存在依赖关系,并且此类是特定于 UI 的。如果这不是一个选项,也可以提取它。当然,如果您愿意,您可以通过缓存结果来避免多次询问用户。

如果及时询问用户不起作用,您可以创建一个抽象,并且两者都CompositeNotificationSender可以MyUserinterfaceWindow依赖它来保存用户的偏好:

public interface IUserLoggingPreference
{
    bool LogToMail { get; set; }
}

MyUserinterfaceWindow或任何其他地方)现在可以依赖IUserLoggingPreference并更改该LogToMail值以更改用户的偏好。将CompositeNotificationSender如下所示:

public class CompositeNotificationSender : INotificationSender {
    private readonly IUserLoggingPreference preference;
    private readonly EmailerNotificationSender mailer;
    private readonly EventLogNotificationSender eventLogger;

    public CompositeNotificationSender(
        IUserLoggingPreference preference,
        EmailerNotificationSender mailer,
        EventLogNotificationSender eventLogger) {
        this.preference = preference;
        this.mailer = mailer;
        this.eventLogger = eventLogger;
    }

    public virtual void SendMessage(string Message) {
        var logger = this.preference.LogToMail ? this.mailer : this.eventLogger;
        logger.SendMessage(Message);
    }
}

这样用户在点击按钮后就不必被提示,并且CompositeNotificationSender独立于用户界面,这使得重用这个逻辑更容易(例如在没有用户交互的系统部分)和它使对此类进行单元测试变得更加容易。

于 2013-08-22T07:04:59.850 回答