首页 > 技术文章 > 设计模式(六) 抽象工厂模式

jasonbourne3 2020-12-07 21:43 原文

设定一个场景:公司要对接两家服务商的业务,业务是相同的,但是两家服务商的接口表现形式是不同的,需要我们对其做一层封装,让它们实现我们统一的接口,以便于公司内部调用。

假设业务包括会员和优惠券两个部分,首先我们需要 创建一个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();
}
View Code

为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();
    }
}
View Code

接下来再为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 = "具体细节"
});
View Code

如果需要调用B服务商的业务,只需要将AErpServiceFactory换成 BErpServiceFactory,就可以完成服务商的转换。

以上就是 抽象工厂模式的简单实现。

优点:

  • 易于更换产品系列,通过调用不同的工厂,可以使用不同的产品配置。
  • 使实例具体的创建过程与客户端分离,客户端不必知道具体实现类名。
  • 易于扩展新的产品系列,只需为新的产品系列创建一个项目实现抽象接口即可,无需更改原有代码。

缺点:

  • 代码量大,增加系统复杂度。
  • 不易于扩展新的产品内部功能,例如增加一个积分服务,需要新增三个类(IScoreService,AScoreService,BScoreService),并且要改动原有的工厂接口增加创建积分服务实例的方法。

推荐阅读