后端开发 AspNetCore 记录使用工厂模式加策略模式解决有多个不同邮件内容的难管理的痛点 L X Y 2025-12-07 2025-12-07
记录使用工厂模式加策略模式解决有多个不同邮件内容的难管理的痛点 那天我正在写一个发送邮件验证码的功能,但是我开始的时候一出手就是if else,这样来判断应该发送什么内容的邮件, 后来我发现这样写太难维护了,然后我又换成了switch case,这样来判断应该发送什么内容的邮件,但是我觉得写太普通了, 所以我又换成了工厂模式加策略模式,这样来判断应该发送什么内容的邮件,这样就很方便了,而且也很好维护。后面需要新增邮件内容的时候, 只需要新增一个策略类,然后在工厂类的字典里面添加新的映射就行。所以我感觉设计模式还是很重要的,让代码更容易维护。不然如果使用if else, 那就需要修改很多地方。
项目文件
appsettings.json IEmailStrategy.cs IEmailStrategyFactory.cs IMailSendService.cs EmailStrategyFactory.cs MailSendService.cs CaptchaConfig.cs // 验证码配置 MailSendServiceConfig.cs // 邮件发送服务配置
appsettings.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { "Logging" : { "LogLevel" : { "Default" : "Information" , "Microsoft.AspNetCore" : "Warning" } } , "ConnectionStrings" : { "DefaultConnection" : "" } , "MailSendServiceConfig" : { "Host" : "smtp.qq.com" , "Port" : 587 , "EmailLocalAddress" : "" , "keyword" : "" } , "SessionConfigure" : { "ExpirationTime" : "3" } , "CaptchaConfig" : { "CaptchaExpirationTime" : "5" } , "AllowedHosts" : "*" }
IEmailStrategy.cs 邮箱策略接口 后面如果需要新增邮件类型,只需要新增一个策略类,然后在工厂类的字典里面添加新的映射就行
1 2 3 4 5 6 7 8 9 namespace DaiBanShiWuList01x02.Interfaces { public interface IEmailStrategy { string Subject { get ; } string BuildBody (string captchaSTR, string effectiveTime ) ; } }
IEmailStrategyFactory.cs 邮箱策略工厂接口
1 2 3 4 5 6 7 8 namespace DaiBanShiWuList01x02.Interfaces { public interface IEmailStrategyFactory { IEmailStrategy GetEmailStrategy (string emailType ) ; } }
IMailSendService.cs 邮件发送服务接口
1 2 3 4 5 6 7 8 9 namespace DaiBanShiWuList01x02.Interfaces { public interface IMailSendService { void SendMailSendService (string SendToMailAdd, string captchaSTR, string emailType ) ; } }
EmailStrategyFactory.cs 邮箱策略工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using DaiBanShiWuList01x02.Interfaces;using DaiBanShiWuList01x02.Services.EmailStrategys;namespace DaiBanShiWuList01x02.Services { public class EmailStrategyFactory : IEmailStrategyFactory { private readonly Dictionary<string , IEmailStrategy> _emailStrategies; public EmailStrategyFactory () { _emailStrategies = new Dictionary<string , IEmailStrategy> { ["AccountRegister" ] = new AccountRegisterEmailStrategy(), ["PasswordForget" ] = new PasswordForgetEmailStrategy(), ["FriendVerification" ] = new FriendVerificationEmailStrategy(), ["AccountLogin" ] = new AccountLoginEmailStrategy(), ["ChangeAccountName" ] = new ChangeAccountNameEmailStrategy() }; } public IEmailStrategy GetEmailStrategy (string emailType ) { _emailStrategies.TryGetValue(emailType, out var strategy); return strategy; } } }
MailSendService.cs 邮件发送服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 using DaiBanShiWuList01x02.Interfaces;using Microsoft.Extensions.Options;using System.Net.Mail;using System.Net;namespace DaiBanShiWuList01x02.Services { public class MailSendService : IMailSendService { private readonly IOptionsMonitor<MailSendServiceConfig> _mailSendServiceConfig; private readonly IOptionsMonitor<CaptchaConfig> _captchaConfig; private readonly IEmailStrategyFactory _emailStrategyFactory; public MailSendService (IOptionsMonitor<MailSendServiceConfig> mailSendServiceConfig, IEmailStrategyFactory emailStrategyFactory, IOptionsMonitor<CaptchaConfig> captchaConfig ) { _mailSendServiceConfig = mailSendServiceConfig; _emailStrategyFactory = emailStrategyFactory; _captchaConfig = captchaConfig; } public void SendMailSendService (string SendToMailAdd, string captchaSTR, string emailType ) { var emailStrategy = _emailStrategyFactory.GetEmailStrategy(emailType); MailMessage mailMessage = new MailMessage { From = new MailAddress(_mailSendServiceConfig.CurrentValue.EmailLocalAddress, "ClipFlow" , System.Text.Encoding.UTF8), To = { new MailAddress(SendToMailAdd) }, Bcc = { new MailAddress(SendToMailAdd) }, Subject = emailStrategy.Subject, SubjectEncoding = System.Text.Encoding.UTF8, IsBodyHtml = true , Body = $@"{emailStrategy.BuildBody(captchaSTR,_captchaConfig.CurrentValue.CaptchaExpirationTime)} " , BodyEncoding = System.Text.Encoding.UTF8 }; SmtpClient smtpClient = new SmtpClient(_mailSendServiceConfig.CurrentValue.Host, _mailSendServiceConfig.CurrentValue.Port); smtpClient.EnableSsl = true ; smtpClient.Credentials = new NetworkCredential(_mailSendServiceConfig.CurrentValue.EmailLocalAddress, _mailSendServiceConfig.CurrentValue.keyword); try { smtpClient.Send(mailMessage); } catch (Exception ex) { Console.WriteLine($"邮件发送失败: {ex.Message} " ); throw ; } } } }
CaptchaConfig.cs 验证码配置
1 2 3 4 5 6 7 8 namespace DaiBanShiWuList01x02 { public class CaptchaConfig { public string CaptchaExpirationTime { get ; set ; } } }
MailSendServiceConfig.cs 邮件发送服务配置
1 2 3 4 5 6 7 8 9 10 11 namespace DaiBanShiWuList01x02 { public class MailSendServiceConfig { public string Host { get ; set ; } public int Port { get ; set ; } public string EmailLocalAddress { get ; set ; } public string keyword { get ; set ; } } }
使用 在控制器里面声明属性:
private readonly IMailSendService _mailSendService; 然后在构造函数中注入:
1 2 3 4 public HomeController (IMailSendService mailSendService ){ _mailSendService = mailSendService; }
在控制器方法中使用:
1 _mailSendService.SendMailSendService(userAccount.Email, loginCaptchaSTR, "AccountLogin" );