设计模式中的那些工厂

Intro

设计模式中有几个工厂模式,聊一聊这几个工厂模式的各自用法和使用示例,工厂模式包含简单工厂,抽象工厂,工厂方法,这些均属于创建型模式, 所谓创建型模式,就是说这几个设计模式是用来创建对象的。

简单工厂

首先来说一说,最简单的简单工厂

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例

严格的来说,简单工厂模式是工厂模式家族中最简单实用的模式,但不属于23种 GOF 设计模式之一。因为每次要新增类型的时候必须修改工厂内部代码,不符合开闭原则。

来看一个例子:

public class OperationFactory
{public static Operation CreateOperation(string operate){Operation operation = null;switch (operate){case "+":operation = new OperationAdd();break;case "-":operation = new OpertaionSub();break;case "*":operation = new OperationMul();break;case "/":operation = new OperationDiv();break;}return operation;}
}

这是一个简单的计算器的示例,支持简单的加减乘除操作,如果要增加一个操作的话就必须要有增加一个 switch ... case 分支,需要修改 CreateOperation 方法不能满足对扩展开放对修改关闭的开闭原则,所以普遍地认为简单工厂不属于设计模式之一,但是我觉得有时候简单的业务处理用简单工厂还是比较方便的。

抽象工厂

抽象工厂模式,提供一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

实现抽象工作模式所需要的组件,主要部分:

  • 抽象工厂/抽象产品

  • 具体工厂1/具体产品1

  • 具体工厂2/具体产品2

  • ...

在客户端根据不同的配置选择不同的工厂,例如根据配置的数据库类型的不同选择使用 Access 数据库仓储的工厂还是使用 SqlServer 数据库的仓储工厂

示例:

IDbFactory factory = new AccessFactory();
var userRepo = factory.CreateUserRepo();
userRepo.Insert(null);
var departmentRepo = factory.CreateDepartmentRepo();factory = new SqlServerFactory();
userRepo = factory.CreateUserRepo();
userRepo.Insert(null);

工厂方法

工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现客户端的操作,也会存在着选择判断的问题,不过和简单工厂相比,简单工厂的选择判断是在工厂内部,而工厂方法则将选择判断转移到了客户端。

示例:

ILeifengFactory factory = new UndergraduteFactory();
var studentLeifeng = factory.CreateLeifeng();
studentLeifeng.BuyRice();factory = new VolunteerFactory();
var leifeng1 = factory.CreateLeifeng();
leifeng1.Sweep();

More

工厂模式的作用无外乎下面这四个。这也是判断要不要使用工厂模式的最本质的参考标准。

  • 封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。

  • 代码复用:创建代码抽离到独立的工厂类之后可以复用。

  • 隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。

  • 控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。

工厂方法和抽象工厂的区别

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类 抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类 区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。

抽象工厂关键在于产品之间的抽象关系,所以一般至少要两个产品;工厂方法在于生成产品,不关注产品间的关系,所以可以只生成一个产品。

抽象工厂更像一个复杂版本的策略模式,策略模式通过更换策略来改变处理方式或者结果;而抽象工厂的客户端,通过更换工厂而改变结果。

工厂方法目的是生产产品,所以能看到产品,而且还要使用产品。当然,如果产品在创建者内部使用,那么工厂方法就是为了完善创建者,从而可以使用创建者。另外创建者本身是不能更换所生产产品的。

抽象工厂的工厂是类;工厂方法的工厂是方法。抽象工厂的工厂类就做一件事情生产产品。生产的产品给客户端使用,绝不给自己用。工厂方法生产产品,可以给系统用,可以给客户端用,也可以自己这个类使用。自己这个类除了这个工厂方法外,还可以有其他功能性的方法。

选择的优化

简单工厂因为选择是在工厂内部的,不符合开闭原则,抽象工厂和工厂方法是将选择权交给客户端,由客户端根据需要自己决定要实例化的工厂。在实际应用的时候大部分情况是只会使用一种工厂,这种情况我们一般可以借助反射+配置来优化选择,如果使用依赖注入,可以直接注入需要的服务即可。

使用反射+配置优化

private static readonly string AssemblyName = "AbstractFactoryPattern";
private static readonly string DbName = ConfigurationHelper.AppSetting("DbName");public static IUserRepo CreateUserRepo()
{return (IUserRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}UserRepo");
}public static IDepartmentRepo CreateDepartmentRepo()
{return (IDepartmentRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}DepartmentRepo");
}

使用依赖注入

依赖注入可以使得我们的代码变得更加良好,扩展性更强。

// 依赖注入
var builder = new ContainerBuilder();
builder.RegisterType<VolunteerFactory>().As<ILeifengFactory>();
builder.RegisterType<SqlServerFactory>().As<IDbFactory>();
var container = builder.Build();var leifengFactory = container.Resolve<ILeifengFactory>();
var volunteer = leifengFactory.CreateLeifeng();
volunteer.Wash();var dbFactory = container.Resolve<IDbFactory>();
dbFactory.CreateDepartmentRepo().CreateDepartment(null);

Reference

  • https://github.com/WeihanLi/DesignPatterns/blob/master/CreatePattern/SimpleFactoryPattern

  • https://github.com/WeihanLi/DesignPatterns/tree/master/CreatePattern/AbstractFactoryPattern

  • https://github.com/WeihanLi/DesignPatterns/blob/master/CreatePattern/FactoryMethodPattern

设计模式中的那些工厂相关推荐

  1. 设计模式中几个工厂模式的比较——餐馆的故事

    初读 Learning Hard大神的作品(C#设计模式总结 - Learning hard - 博客园),略有感触.对创建型模式中的简单工厂模式.工厂方法模式和抽象工厂模式这三个既有共性又有区别的模 ...

  2. java工厂模式和抽象工厂_Java中的抽象工厂设计模式

    java工厂模式和抽象工厂 Welcome to Abstract Factory Design Pattern in java example. Abstract Factory design pa ...

  3. 理解设计模式中的工厂模式

    在理解设计模式中的单例模式一文中介绍了创建型模式中最为简单的一种:单例模式,并推荐了几种可以在实际生产中使用的线程安全的形式.本文将继续介绍创建型模式中的工厂方法模式和抽象工厂模式,同样使用代码和类图 ...

  4. 设计模式-抽象工厂模式的应用场景及Java中对抽象工厂的应用

    1. 什么是抽象工厂模式 抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定他们的类 抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用 ...

  5. 设计模式学习笔记(三)工厂模式中的简单工厂、工厂方法和抽象工厂模式之间的区别

    设计模式中的工厂模式(Factory Design pattern)是一个比较常用的创建型设计模式,其中可以细分为三种:简单工厂(Simple Factory).工厂方法(Factory Method ...

  6. 设计模式 笔记4 | 简单工厂模式 在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式

    文章目录 一.Calendar 日历类 1.1 内部属性 1.2 设置时间属性值 1.3 获取时间属性 1.4 使用 Calander 计算时间 二.Calender 类中的设计模式 2.1 简单工厂 ...

  7. 工厂设计模式(java版本、spring源码中使用的工厂模式)

    最近在学习spring源码,发现在IoC容器初始化的时候创建各种bean,然后在代码中看到各种beanFactory和factoryBean,很显然spring容器在创建bean的过程是使用了工厂设计 ...

  8. 简单工厂模式-接口在设计模式中的应用之一

    接口在设计模式中的应用之一:简单工厂模式 无工厂:手工 缺点:麻烦,对每一个的要求都比较高 优点:个性化 工厂:生产产品 优点:批量生产,使用者比较方便,直接买 缺点:无法定制,如果非要定制就会比较麻 ...

  9. 设计模式C#描述——抽象工厂模式

    设计模式C#描述--抽象工厂模式 阅读此文应先阅读简单工厂模式与工厂方法模式 抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广. 假设一个子系统需要一些产品对象,而这些产品又属于一个以上的产 ...

最新文章

  1. c语言杨辉三角的实现
  2. 深入浅出MyBatis-快速入门
  3. 学 AI 和机器学习的人必须关注的 6 个领域
  4. 关于共享单车的供电问题如何解决?
  5. Laplacian matrix 从拉普拉斯矩阵到谱聚类
  6. 在欲而无欲,居尘不染尘
  7. 经典知识:交互设计规范8大总结!附84页资料:《J 东交互设计规范》
  8. 【2016年第6期】情境大数据建模及其在用户行为预测中的应用
  9. 转:Vim中显示不可见字符
  10. ajax前端post请求json格式参数,前端js导出,参数以json格式发送post请求
  11. python数据结构剑指offer-构建乘积数组
  12. 所谓的日常 #10 - 勤王室馬騰舉義 報父仇曹操興師
  13. 一个小小的发现--音频也八卦
  14. python安装pygame教程_python-pygame安装教程
  15. 抠图 php中文网,ps cs3怎么抠图
  16. android 离线音乐播放器,5款顶级Android离线音乐播放器,哪款才是你的菜?
  17. 虚拟机 VMware Workstation 16 PRO 的网络配置
  18. Excel制作增长趋势图
  19. 你为什么要离开上一家公司?
  20. 云原生大数据平台零信任网络安全实践技术稿

热门文章

  1. .NET平台下几种SOCKET模型的简要性能供参考
  2. 点击User Profile Service Application 报错
  3. [WCF安全系列]认证与凭证:用户名/密码认证与Windows认证
  4. java allocate_Java中volatile关键字的最全总结
  5. safari 获取视频流_如何在Safari中将RSS feed和社交媒体合并为一个流
  6. 甘特图看起来很生硬?教你使用智能颜色装饰你的甘特图!(二)
  7. 上周面试回来后写的Java面试总结,想进BAT必看
  8. 光纤熔接过程详细说明
  9. oracle的本地安装和PUTTY+XMING远程连接安装和oracle翻页功能
  10. 新型互联网交换中心促进互联网产业发展,助力信息经济创新