设计模式中的那些工厂

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

(0)

相关推荐

  • 创建型模式

    title: "[设计模式]创建型模式" date: 2016-03-07 18:05 tags: 设计模式 design pattern creational factory m ...

  • 创建型设计模式总结

    Intro 前面几篇文章已经把创建型设计模式都介绍了,来做一个简单的总结. 创建型设计模式,就是用来创建对象的设计模式,根据要创建的对象的复杂度以及是否允许多实例以及是否需要容易扩展等多方面考虑去选择 ...

  • 设计模式之享元模式

    享元模式 Flyweight Intro 享元是指一个可复用的对象,通过复用这个享元来减少应用中的内存分配. 享元模式是为了减少内存占用,尽可能复用已有对象的设计模式,一般来说会把这个可复用的对象放到 ...

  • 设计模式(1) 工厂方法模式

    创建型模式 简单工厂模式 工厂方法模式 IOC与工厂方法模式的结合 泛型工厂 委托工厂 创建型模式 创建型模式可以隔离客户程序对需要实例化类型的依赖关系,这类模式一般通过将实例化具体对象的职责委托给第 ...

  • [PHP小课堂]PHP设计模式之工厂方法模式

    [PHP小课堂]PHP设计模式之工厂方法模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 【重温设计模式】之002简单工厂模式

    [重温设计模式系列源码] 简单工厂模式 基本原理 含义 简单工厂模式又叫静态方法模式(因为工厂类定义了一个静态方法). 在现实生活中,工厂是生产产品的, 同样的,在设计模式中,一个负责生产" ...

  • 中国是世界工厂?外国小伙在中国用零件拼凑出苹果手机,惨遭打脸

    喜欢看视频的朋友点点"在看"或者是蓝色字体"搞机二师兄"关注以资鼓励,谢谢!

  • 【C++设计模式二】C++工厂模式

    (1)定义 简单工厂模式中,每新增一个具体产品,就需要修改工厂类内部的判断逻辑.为了不修改工厂类,遵循开闭原则,工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂, ...

  • 设计模式学习笔记 ———— 简单工厂模式

    # 背景 简单工厂模式是很多程序员学习的第一个设计模式,因为其不但原理简单而且易于上手,在日常工作的代码中也常有体现.今天分享一个基于实现"加"."减".&qu ...

  • 设计模式-创建型-抽象工厂模式

    前一章节,我们介绍了简单工厂模式以及工厂方法模式,但是这两种模式都存在一定的局限性,只能生产某一类型下的某一种产品,如果需求变更,同类型下出现了不同的产品,比如芝士披萨不仅有口味上的不同,同时存在外观 ...

  • 玉米行情稳中趋弱,工厂小幅度调整收购的价格!

    养猪朋友们大家好,我是主播婉婷,今天视频栏目的主题词是玉米价格,近期玉米行情稳中趋弱表现,多家工厂继续小幅度调整收购的价格,不过由于近期物流运输情况并不理想,价格偶尔波动,影响也并不大!眼看着要过年了 ...

  • 设计模式中的观察者模式

    观察者模式是一种软件设计模式,其中一个名为主体(Subject)的对象维护其依赖项列表,称为观察者,并通常通过调用它们(observers)的方法之一来自动通知它们任何状态更改. 观察者模式主要用于在 ...

  • 推荐!马德里巧克力工厂,现实中的糖果世界!

    「马德里巧克力工厂」马德里最受欢迎的时尚打卡地点之一! 当你还是一个小孩子的时候,你可能幻想过自己某一天进入了神奇的糖果幻想世界,就如同电影<查理和巧克力工厂>里展现的那样,一群小孩子在魔 ...

  • 肥多多宜昌云工厂——茂隆中孚考察调研

    4月15日,国联股份总裁钱晓钧.肥多多CEO尹海凤.肥多多战略合作伙伴吕文.肥多多宜昌云工厂运营公司CEO熊宏国一行赴战略合作云工厂--湖北中孚化工集团有限公司(茂隆中孚)考察调研.茂隆中孚总经理尹代 ...

  • 中国是资本暴利的终结者,技术垄断的粉碎机#实体店 #制造 #实体数字化转型 #工厂 #灯课堂 #国...

    中国是资本暴利的终结者,技术垄断的粉碎机#实体店 #制造 #实体数字化转型 #工厂 #灯课堂 #国...