【问题标题】:best practice for using decorator for send notification in asp core在 asp 核心中使用装饰器发送通知的最佳实践
【发布时间】:2020-04-22 04:56:08
【问题描述】:

我需要通过短信或电子邮件发送通知,我为此由Decorator Pattern 编写代码。

但我不知道我写的是不是正确的,因为当我需要使用多种方式(电子邮件和短信)时它不能很好地工作。

查看代码:

public abstract class Notification
{
    public abstract Task<OperationResult<string>> Send(string from, string subject, string content, string userName, string password, MailboxAddress to, int port, string smtpServer);
    public abstract Task<OperationResult<string>> Send(string lineNumber, string userApiKey, string phoneNumber, string message, string secrectKey);
}

我有两个方法 Send 因为它们有不同的论点。

我在这个类中实现了Notification

 public class SendNotification : Notification
{
    public SendNotification()
    {
    }
    /// <summary>
    /// Send Email Notifiaction
    /// </summary>
    /// <param name="from"></param>
    /// <param name="subject"></param>
    /// <param name="content"></param>
    /// <param name="userName"></param>
    /// <param name="password"></param>
    /// <param name="to"></param>
    /// <param name="port"></param>
    /// <param name="smtpServer"></param>
    /// <returns></returns>
    public override async Task<OperationResult<string>> Send(string from, string subject, string content, string userName, string password, MailboxAddress to, int port, string smtpServer)
    {
        using (var client = new SmtpClient())
        {
            var emailMessage = new MimeMessage();
            try
            {
                client.Connect(smtpServer, port, true);
                client.AuthenticationMechanisms.Remove("XOAUTH2");
                client.Authenticate(userName, password);
                emailMessage.From.Add(new MailboxAddress(from));
                emailMessage.To.Add(to);
                emailMessage.Subject = subject;
                emailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Text) { Text = content };
            }
            catch (Exception ex)
            {
                return OperationResult<string>.BuildFailure(ex);
            }
            finally
            {
                await client.DisconnectAsync(true);
                client.Dispose();
            }
        }
        return OperationResult<string>.BuildSuccessResult("Success Send Email");
    }


    /// <summary>
    /// Send Sms Function
    /// </summary>
    /// <param name="lineNumber"></param>
    /// <param name="userApiKey"></param>
    /// <param name="phoneNumber"></param>
    /// <param name="message"></param>
    /// <param name="secrectKey"></param>
    /// <returns></returns>
    public override async Task<OperationResult<string>> Send(string lineNumber, string userApiKey, string phoneNumber, string message, string secrectKey)
    {
        var token = new Token().GetToken(userApiKey, secrectKey);

        var restVerificationCode = new RestVerificationCode()
        {
            Code = message,
            MobileNumber = phoneNumber
        };

        var restVerificationCodeRespone = new VerificationCode().Send(token, restVerificationCode);
        if (restVerificationCodeRespone.IsSuccessful)
        {
            return OperationResult<string>.BuildSuccessResult(restVerificationCodeRespone.Message);
        }
        return OperationResult<string>.BuildFailure(restVerificationCodeRespone.Message);
    }
}

现在我创建了SendSmsSend Email 类:

电子邮件:

 public class NotificationEmail : SendNotification
{
    private readonly Notification notification;

    public NotificationEmail(Notification notification) 
    {
        this.notification = notification;
    }

    public override Task<OperationResult<string>> Send(string from, string subject, string content, string userName, string password, MailboxAddress to, int port, string smtpServer)
    {
        return base.Send(from, subject, content, userName, password, to, port, smtpServer);
    }
}

短信:

 public class NotificationSms : SendNotification
{
    private readonly Notification notification;

    public NotificationSms(Notification notification) 
    {
        this.notification = notification;
    }

    public override Task<OperationResult<string>> Send(string lineNumber, string userApiKey, string phoneNumber, string message, string secrectKey)
    {
        return base.Send(lineNumber, userApiKey, phoneNumber, message, secrectKey);
    }
}

现在我在课堂上通过这种方式使用此代码:

SendNotification notif = new SendNotification();
NotificationSms smsSend = new NotificationSms(notif);
NotificationEmail emailSend = new NotificationEmail(smsSend);
var sendSms = await smsSend.Send(smsSetting.Result.LineNumber, smsSetting.Result.userApikey, to, content, smsSetting.Result.secretKey);
var sendEmail = await emailSend.Send(emailSetting.Result.From, "Email Confirm Code", content, emailSetting.Result.Username, emailSetting.Result.Password, to, emailSetting.Result.Port, emailSetting.Result.SmtpServer);

现在我需要使用装饰器的最佳实践。如何改进我的代码和装饰器中的最佳设计???

【问题讨论】:

    标签: c# asp.net asp.net-core design-patterns


    【解决方案1】:

    你为什么要强迫自己使用装饰器模式,而不仅仅是使用更合适的策略模式或模板方法模式。

    装饰器模式是为了增加责任......但你不是在增加责任,你是在用它的主要功能装饰一个对象......不要为此使用装饰器。

    我建议使用策略模式

    一些文档:https://en.wikipedia.org/wiki/Strategy_pattern

    TL:DR:使用组合,您可以使用其适当的行为构造一个对象。对你来说,我会说你需要一个抽象发送行为的接口,并有 2 个实现......用于短信和电子邮件。 构建完成后,只需使用短信或电子邮件编写 sendnotification 对象

    【讨论】:

      【解决方案2】:

      我会选择将配置与实际消息分开,并将其作为实际发送实现的依赖项。将其与实际消息分开,您可以创建一个可用于各种渠道的简单界面。

      除非您想在实际调用中添加某种行为,否则装饰器并不是必需的。

      public interface INotification
      {
          Task<OperationResult<string>> Send(string subject, string message);
      }
      
      public class SmsNotfication : INotification
      {
          public SmsNotfication(string lineNumber, string userApiKey, string phoneNumber, string secrectKey)
          {
      
          }
      
          public Task<OperationResult<string>> Send(string subject, string message);
          {
              var token = new Token().GetToken(userApiKey, secrectKey);
      
              var restVerificationCode = new RestVerificationCode()
              {
                  Code = message,
                  MobileNumber = phoneNumber
              };
      
              var restVerificationCodeRespone = new VerificationCode().Send(token, restVerificationCode);
              if (restVerificationCodeRespone.IsSuccessful)
              {
                  return OperationResult<string>.BuildSuccessResult(restVerificationCodeRespone.Message);
              }
              return OperationResult<string>.BuildFailure(restVerificationCodeRespone.Message);
          }
      }
      
      public class MailNotification : INotification
      {
          public MailNotification(string from, string userName, string password, MailboxAddress to, int port, string smtpServer)
          {
      
          }
      
          public Task<OperationResult<string>> Send(string message, string content)
          {
              using (var client = new SmtpClient())
              {
                  var emailMessage = new MimeMessage();
                  try
                  {
                      client.Connect(smtpServer, port, true);
                      client.AuthenticationMechanisms.Remove("XOAUTH2");
                      client.Authenticate(userName, password);
                      emailMessage.From.Add(new MailboxAddress(from));
                      emailMessage.To.Add(to);
                      emailMessage.Subject = subject;
                      emailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Text) { Text = content };
                  }
                  catch (Exception ex)
                  {
                      return OperationResult<string>.BuildFailure(ex);
                  }
                  finally
                  {
                      await client.DisconnectAsync(true);
                      client.Dispose();
                  }
              }
              return OperationResult<string>.BuildSuccessResult("Success Send Email");
          }
      }
      
      public class ConsoleLoggingNotificationDecorator : INotification
      {
          private readonly INotification _notification;
          public ConsoleLoggingNotificationDecorator(INotification notification) => _notification = notification;
      
          public Task<OperationResult<string>> Send(string message, string content)
          {
              System.Console.WriteLine("Sending message in notification channel");
              var result = _notification.Send(message, content);
              System.Console.WriteLine("Message has completed send in notification channel");
              return result;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-05-04
        • 2017-03-05
        • 1970-01-01
        • 2018-06-08
        • 1970-01-01
        • 2014-08-29
        • 2014-04-11
        • 1970-01-01
        • 2010-10-22
        相关资源
        最近更新 更多