设计模式(六) 抽象工厂模式
设定一个场景:公司要对接两家服务商的业务,业务是相同的,但是两家服务商的接口表现形式是不同的,需要我们对其做一层封装,让它们实现我们统一的接口,以便于公司内部调用。
假设业务包括会员和优惠券两个部分,首先我们需要 创建一个ErpService.Abstract项目,并为这两个业务定义两个统一的接口以及一个抽象工厂接口。
//会员接口 public interface IVipService { int AddVip(Vip vip); } //优惠券接口 public interface ICouponService { int AddCouponPlan(CouponPlan couponPlan); } public class Vip { public string mobile { get; set; } public string vipName { get; set; } public short sex { get; set; } } public class CouponPlan { public int planId { get; set; } public string planName { get; set; } public string remark { get; set; } } //抽象工厂接口 public interface IErpServiceFactory { IVipService GetVipInstance(); ICouponService GetCouponInstance(); }
为A服务商创建一个 ErpService.A的项目,创建两个类实现上面两个接口,并创建一个工厂类实现抽象工厂接口
public class VipService : IVipService { public int AddVip(Vip vip) { Console.WriteLine("A服务商注册会员"); // todo : return 1; } } public class CouponSerivce : ICouponService { public int AddCouponPlan(CouponPlan couponPlan) { Console.WriteLine("A服务商创建券方案"); // todo : return 1; } } //A服务商服务工厂类 public abstract class AErpServiceFactory : IErpServiceFactory { public ICouponService GetCouponInstance() { return new CouponSerivce(); } public IVipService GetVipInstance() { return new VipService(); } }
接下来再为B服务商创建一个 ErpService.B的项目(做A项目同样的操作,这里不再用代码展示)。
客户端代码如下:
var erpServiceFactory = new AErpServiceFactory(); var vipService = erpServiceFactory.GetVipInstance(); var couponService = erpServiceFactory.GetCouponInstance(); vipService.AddVip(new Vip() { mobile = "11", vipName = "张三", sex = 1 }); couponService.AddCouponPlan(new CouponPlan() { planId = 1, planName = "测试方案", remark = "具体细节" });
如果需要调用B服务商的业务,只需要将AErpServiceFactory换成 BErpServiceFactory,就可以完成服务商的转换。
以上就是 抽象工厂模式的简单实现。
优点:
- 易于更换产品系列,通过调用不同的工厂,可以使用不同的产品配置。
- 使实例具体的创建过程与客户端分离,客户端不必知道具体实现类名。
- 易于扩展新的产品系列,只需为新的产品系列创建一个项目实现抽象接口即可,无需更改原有代码。
缺点:
- 代码量大,增加系统复杂度。
- 不易于扩展新的产品内部功能,例如增加一个积分服务,需要新增三个类(IScoreService,AScoreService,BScoreService),并且要改动原有的工厂接口增加创建积分服务实例的方法。