Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 如何提取具体类型的依赖关系?_Design Patterns_Dependency Injection_Factory_Abstract Factory - Fatal编程技术网

Design patterns 如何提取具体类型的依赖关系?

Design patterns 如何提取具体类型的依赖关系?,design-patterns,dependency-injection,factory,abstract-factory,Design Patterns,Dependency Injection,Factory,Abstract Factory,我有一个要求,用户需要配置在发生错误时如何获得警报。他们有以下几种选择: 一,。在事件日志中创建事件 二,。将电子邮件发送到从用户界面指定的电子邮件 interface INotificationSender { virtual void SendMessage(string message); } 我当前使用的类使用以下接口 interface INotificationSender { virtual void SendMessage(string message); } 我

我有一个要求,用户需要配置在发生错误时如何获得警报。他们有以下几种选择:

一,。在事件日志中创建事件

二,。将电子邮件发送到从用户界面指定的电子邮件

interface INotificationSender
{
   virtual void SendMessage(string message);
}
我当前使用的类使用以下接口

interface INotificationSender
{
   virtual void SendMessage(string message);
}
我的接口将由以下两个具体类实现

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的具体构造函数需要字符串参数

将两个实现隐藏在INotificationSender实现后面

如果您可以延迟用户选择要登录的源,那么可以将选择逻辑移动到组合中,这样可以防止该逻辑干扰MyUserinterfaceWindow。下面是一个例子:

公共类CompositeNotificationSender:INotificationSender{ 私人只读电子邮件通知发送人邮件; 私有只读事件日志NotificationSender事件记录器; 公共复合发送器 EmailrNotificationSender mailer, EventLogNotificationSender事件记录器{ this.mailer=mailer; this.eventLogger=eventLogger; } 公共虚拟空SendMessagestring消息{ bool logToMail=AskUserWhereToLog; var logger=logToMail?this.mailer:this.eventLogger; logger.SendMessageMessage; } 二等兵布尔阿斯库瑟霍雷托洛格{ //待办事项: } } 由于该类询问用户,因此与UI存在依赖关系,并且该类是特定于UI的。如果这不是一个选项,也可以提取它。当然,如果您愿意,您可以通过缓存结果来避免多次询问用户

如果及时询问用户不起作用,您可以创建一个CompositeNotificationSender和MyUserinterfaceWindow都可以依赖的抽象,它可以保存用户的首选项:

公共接口IUserLoggingPreference { bool LogToMail{get;set;} } MyUserinterfaceWindow或任何其他位置现在都可以依赖于IUserLoggingPreference并更改LogToMail值来更改用户的首选项。CompositeNotificationSender将如下所示:

公共类CompositeNotificationSender:INotificationSender{ 私有只读IUserLoggingPreference; 私人只读电子邮件通知发送人邮件; 私有只读事件日志NotificationSender事件记录器; 公共复合发送器 I记录偏好, EmailrNotificationSender mailer, EventLogNotificationSender事件记录器{ 这个。偏好=偏好; this.mailer=mailer; this.eventLogger=eventLogger; } 公共虚拟空SendMessagestring消息{ var logger=this.preference.LogToMail?this.mailer:this.eventLogger; logger.SendMessageMessage; } }
这样,用户单击按钮后无需提示,并且CompositeNotificationSender独立于用户界面,这使得在没有用户交互的系统部分更容易重用此逻辑,并且更容易对此类进行单元测试。

为什么警报配置窗口会有SendAlert方法?如果您将用户首选项存储在某个位置,而不是在窗口中使用硬连线的m_NotificationSender,则可以根据配置在需要时动态实例化NotificationSender。