工厂模式是最常用的设计模式之一,属于创建型模式。
有点:
当一个抽象类有多个实现的时候,需要多次实例化的时候,就要考虑使用工厂模式。
比如:登录的抽象类ILoginBusiness,它有2个实现,一个用用户名密码登录,一个用手机号验证码登录
public interface ILoginBusiness{ Task Login(LoginInputDTO input);}public class MobileCodeLogin : ILoginBusiness{ public Task Login(LoginInputDTO input) { // todo }}public class UserNameAndPasswordLogin : ILoginBusiness{ public Task Login(LoginInputDTO input) { // todo }}按照原有方式,我们会根据某个条件去实例化,比如loginType
ILoginBusiness loginBusiness;if (loginType == 1){ loginBusiness = new MobileCodeLogin();}else{ loginBusiness = new UserNameAndPasswordLogin()}当有多种实例的话,就需要更多的ifelse或者switch,工厂模式的作用就是把这种建造对象的方法放在工厂类去解决,统一管理统一维护。
public interface ILoginFactory{ ILoginBusiness Create(LoginInputDTO inputDto);}public class LoginFactory : BaseBusiness, ILoginFactory, ITransientDependency{ public ILoginBusiness Create(LoginInputDTO inputDto) { return inputDto.LoginType == LoginType.UserNameAndPwd ? AppDependencyResolver.Current.GetService<UserNameAndPwdLogin>() : (ILoginBusiness)AppDependencyResolver.Current.GetService<MobileCodeLogin>(); } public LoginFactory(IRepository repository) : base(repository) { }}如果用new的方法去实例化,就需要把构造方法中的参数在工厂的构造方法里也加入进去,所以这里用了一个AppDependencyResolver,这里的AppDependencyResolver.Current.GetService<T>是从当前IOC容器中获取注入的实例,所以之前的MobileCodeLogin和UserNameAndPasswordLogin需要注入到IOC实例中,在我们项目就是继承ITransientDependency
public class AppDependencyResolver{ private static AppDependencyResolver _resolver; public static AppDependencyResolver Current { get { if (_resolver == null) throw new Exception("AppDependencyResolver not initialized"); return _resolver; } } // 在startUp的ConfigureService的最后,加入AppDependencyResolver.Init(services.BuildServiceProvider()); public static void Init(IServiceProvider service) { _resolver = new AppDependencyResolver(service); } private AppDependencyResolver(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } private readonly IServiceProvider _serviceProvider; public object GetService(Type serviceType) { return _serviceProvider.GetService(serviceType); } public T GetService<T>() { return _serviceProvider.GetService<T>(); }}关于工厂,我们只需要测返回的对象是否是我们需要的就可以了,至于对象的执行对不对不需要关心
[Theory(DisplayName = "测试登录工厂")][InlineData(LoginType.MobileCode, typeof(MobileCodeLogin))][InlineData(LoginType.UserNameAndPwd, typeof(UserNameAndPwdLogin))]public void CreateTests(LoginType loginType, Type expectedType){ Mock<IRepository> mock = new Mock<IRepository>(); ILoginFactory factory = new LoginFactory(mock.Object); var login = factory.Create(new LoginInputDTO() { LoginType = loginType }); Assert.IsType(expectedType, login);}