> 文档中心 > 【BlankFox学习笔记-设计模式】Factory工厂模式——更灵活的创建实例

【BlankFox学习笔记-设计模式】Factory工厂模式——更灵活的创建实例

Factory——更灵活的创建实例

笔记版本:2.0
作者:BlankFox(CSDN主页)
归档:设计模式浅谈
【BlankFox学习笔记-设计模式】Factory工厂模式——更灵活的创建实例

写在前面:

ps: 所谓 设计模式 就是前人总结的良好代码模板——想象一下:当在求职时被问到一个大概的需求时,能够清晰直接的对他说:“根据XXX设计模式的思想,可以设计如下几个角色…”——这种就好像英语等级考试的作文,恰好命中了你背的那篇模板,清晰的思路以及良好的扩展性和易于理解的结构,会让你爱上你的代码❤️

ps:Factory模式——创建方法的集合,帮助创建对象的”工具人”
(能够让接口使用者对具体实例哪个类隐藏,根据传入的参数选择类实现,使得对象构建更容易理解,如下)

public static void main(String[] args){ Entity entity1=new ConcreteEntity_1(1,2,"name","passwd",new Setting(1,0)); Entity entity2=new ConcreteEntity_2(0,2,"name2","passwd2");}//Factory设计使用时如下,不用再纠结是1,还是2了public static void main(String[] args){ EntityFactory factory=new EntityFactory(); Entity entity1=factory.creatEntity(1,2,"name","passwd",new Setting(1,0)); Entity entity2=factory.creatEntity(0,2,"name2","passwd2");}

Factory工厂模式——更灵活的创建实例

      • 一、概念
      • 二、理解指南
        • 2.1理解引入和说明
        • 2.2示例代码
      • 三、作用解析
      • 四、简单工厂模式、工厂方法模式、抽象工厂模式?(该部分待修改)
      • 欢迎关注我、共勉:star:

一、概念

工厂模式:简单的说就是包装构造函数使之更灵活的构造对象,定义一个类来负责对象的创建的一种设计思维。下面简单区别一下三种工厂模式(从简单到复杂)

  1. 简单工厂(Sample Factory):使用一个类(工厂)来负责一个类(产品)的多种变体的对象的创建(一 个 产 品 多 种 创 建 方 式 , 使 用 同 名 的 构 造 函 数 不 好 区 别 \color{green}{一个产品多种创建方式,使用同名的构造函数不好区别}使
  2. 工厂方法(Factory Method):使用一个父类(提取工厂方法的类)抽取多个工厂类相同的部分,留下具体创建给其自行实现( \color{green}{} 多 个 工 厂 对 产 品 的 处 理 流 程 相 似 , 只 是 创 建 的 产 品 有 别 \color{green}{多个工厂对产品的处理流程相似,只是创建的产品有别}
  3. 抽象工厂(Abstract Factory):使用抽象父类接口,约定能够创建多种产品,但是实际的产品创建需要由具体工厂类实现(意 思 是 , 不 同 的 工 厂 能 够 创 建 不 同 “ 型 号 ” 的 多 个 同 名 产 品 \color{green}{意思是,不同的工厂能够创建不同“型号”的多个同名产品}

从工厂模式的定义可以看出:它是为了创建对象服务的,属于创建型模式的一种——为了实现更好的创建对象的方式

  • 使得更直观,避免同名构造函数过多
  • 责任更集中,对象的产生集中在一个类里面
  • 更易扩展,面向接口而不是面向具体对象

二、理解指南

2.1理解引入和说明

创建对象?不就是new吗,有什么难的…大不了多写几个new罢了🃏

想象一下:当你面对超过10个以上构造函数的类被一堆类创建使用,而且突然发现这个类有bug需要修改的时候,你不得不去挨个查找引用,并修改构造函数的传入参数(这时候你修改完了又发现你某个参数好像写错了…remake毁灭吧)

user user=new User("普通用户","密码",0);User user=new User("管理者","密码",1);//如果任意使用的话,最后一个参数0,1是很难区分和没有太大字面意义的,为什么不这样...user user=creatNomalUser("普通用户","密码");User user=creatRootUser("管理者","密码");

更好理解示例代码:

  • 被冠以模式名称的类是实现该模式功能的主要支撑者
  • 使用Core命名的类主要是该模式核心角色管理的对象
  • 使用Client命名的类是模式的使用者
  • 在该模式中——Factory类管理和包装Core对象的创建,Client通过Factory获取需要的Core

2.2示例代码

现在是时候让简单工厂模式大显身手了——Sample Factory,超级简单的构建一个简单工厂

示 例 . 1 — — 简 单 工 厂 构 建\color{red}{示例.1——简单工厂构建} .1

//示例.1——简单工厂构建,假设Core是一个表示矩形和位置的类(x,y,length,wide)class SampleFactory{    public Core creatDefaultCore(){ return new Core(0,0,16,16);    }    public Core creatNomalCore(x,y,l,w){ return new Core(x,y,l,w);    }    public Core creatSpecialCore(x,y,l){ return new Core(x,y,l,l);    }    ....}public class Client{    ...    public void draw(){ /* 创建一个工厂来负责生成Core的各种对象,实现了对象创建与使用解耦 */ Core c=sampleFactory.creatDefaultCore(); //toDraw c    }}

更普遍的定义简单工厂模式——实现了构造函数封装的类

示 例 . 2 — — 实 现 自 我 构 造 封 装 的 静 态 构 造 工 厂\color{red}{示例.2——实现自我构造封装的静态构造工厂} .2

//示例.2——实现自我构造封装的静态构造工厂class Core{    private Core(...){}    /** 封装独特的构造函数,或者相当于给构造函数重命名一下 */    public static Core createSpecialCore(...){ //do something return specialCore;    }}

封装相同方法,同时保留了不同的对象创建方式使用工厂方法模式——Factory Method求同存异

示 例 . 3 — — 如 何 实 现 一 个 工 厂 方 法 模 式\color{red}{示例.3——如何实现一个工厂方法模式} .3

//示例.3——如何实现一个工厂方法模式abstract class FactoryMethod{ /* 避免了这部分逻辑代码重复,也便于修改共用的逻辑 */    public void sameFunction(){ //all Factories need to do some Core c=creatCore(); //all Factories need to do some    } /* 具体的工厂负责创建自己独特的Core子类 */    abstract Core creatCore();}/* 具体的工厂类,不用再实现一大堆公用逻辑代码了 */class concreteFactory extend FactoryMethod{    @Override    public Core creatCore(){ return new SpecialCore();    }}/* 使得代码依赖接口,更加泛用 */class SpecialCore impliments Core{    ...}

为多个对象提供不同类型的创建服务,这太难为我抽象工厂了——Abstract Factory,不就是创建对象吗!

示 例 . 4 — — 为 W i n d o w s 和 M a c 提 供 切 换 服 务 ( 为 不 同 版 本 切 换 做 准 备 )\color{red}{示例.4——为Windows和Mac提供切换服务(为不同版本切换做准备)} .4WindowsMac()

//示例.4——为Windows和Mac提供切换服务abstract class AbstractFactory{    abstract CoreA creatCoreA();    abstract CoreB creatCoreB();}class WindowsFactory extends AbstractFactory{    public CoreA creatCorA(){ return new CoreAForWindows();//继承了CoreA    }    public CoreB creatCorB(){ return new CoreBForWindows();//继承了CoreA    }}class MacFactory extends AbstractFactory{    ...}class Client{    public Test(){ AbstractFactory factory=new WindowsFactory(); /** 现在下面创建的Core对象都是为了Windows服务的特殊Core /* 要修改为Mac版本也很容易,factory=new MacFactory() /* 只需要换一个Factory的具体实例即可,这也是该模式的优点 */ CoreA coreA=factory.creatCoreA(); //do something    }}

三、作用解析

莽能解决100行代码以内的问题,但不能解决1000行代码的问题,但是良好的设计可以

在学习设计模式的过程中要始终记住——设计模式是为了更好的扩展代码和更清晰的理解代码,而不是生搬硬套,就比如说:不是只有Factory命名才叫工厂模式,而是实现了对对象构建的封装的类叫Factory类(命名需要精简适用)

Sample Factory(简单工厂模式):提供了对单个类的多种构建方法的封装,实现了对构造函数重命名构造预处理的作用——使得构建对象的选择更清晰,同时使得对象构建和对象使用解耦(在使用代码中不在包含new+具体类),而使用工厂隔离了对象的具体构造(便于后期修改构造过程)

Factory Method(工厂方法模式):提供对多种特殊对象的构建接口,使用统一接口包装不同构造过程,并能够提取出共同方法到更上层,解决了大体类似的逻辑过程中包含特殊构造对象的特殊性,使得能够一次修改共用的逻辑代码(这部分叫工厂方法),而具体的对象构建交给子工厂执行(这部分属于简单工厂)

**Abstract Factory(抽象工厂模式):**提供对多个对象的不同版本的创建封装,通过抽象工厂定义产品,具体工厂实现具体版本产品的创建过程,不同版本产品又使用统一的产品父类引用,实现了切换具体工厂达到一次性切换对象版本的问题(抽象工厂和工厂方法有类似之处,但是针对问题不同——抽象工厂针对对象的不同版本实现(主切分),而工厂方法针对代码中相同部分提取出不同对象构建(主统一))

四、简单工厂模式、工厂方法模式、抽象工厂模式?(该部分待修改)

4.1 简单工厂模式:具体就是创建一个工厂类,负责创建出一个具体的对象同时可能负责一些对象构建的配置。(注意其中的判断和原本的代码可能没有什么区别,只是避免了它出现在主体代码中让你心烦——实现了责任的转移)

4.2 工厂方法模式:创建多个工厂分别负责各自对象的创建,其好处是避免了复杂判断,也可以利用多态和反射动态修改创建方法。但是类更多了,更复杂。(我一般把它理解成一个工厂-多条流水线的方法)

比如如下的代码:

static void main(String[] args){Factory factory=null;while(1){factoryFlowline="//输入流水线名字"//反射方法,动态创建类//创建一个类名为"factoryFlowline"的实例factory=(Factory)Class.forName(factoryFlowline).newInstace();Car car=factory.creatNewCar(carType);car.printMessage();}}

类图如下:
在这里插入图片描述
把工厂作为一个父类总体,然后派生出一系列子类(这里我称为工厂中的产业流水线),由具体的子类负责创建不同的产品对象。该模式具有更高的扩展性,且不会影响原有的类,实现了判断产品逻辑的切分。

  • 和上面那个方法比较,考虑添加一个新产品类的情况,不难发现工厂方法类不需要修改任何现有的类,而是直接添加一个产品类和相应的工厂方法类(产业流水线类)。不过类明显变多了,而且用起来没有之前那个简单版本方便——好的结构往往以复杂的设计收场,在实际设计中谨慎取用

4.3 抽象工厂模式:创建多个工厂分别负责多个对象的创建,在工厂方法模式的基础上,增加了原来简单工厂模式的特点,解决的是不同工厂生产不同产品不同型号的问题。(比如A工厂加工国内销售汽车,B工厂生产出口汽车——生产的产品种类相同,但是总的标准不同)

这里直接用类图讲解:
在这里插入图片描述简单的说:就是创建两种标准下的多种产品的问题,为了实现良好的类间解耦,采用了更复杂的抽象工厂模式——顾名思义,工厂成为了抽象的父类,每个具体的工厂实现都要负责各自标准下的多种对象的创建工作。{ 产品数目(m)x 标准数目(n)+产品父类(m)+工厂父类(1)} 使得该模式在简单情况下就显得很复杂。

  • 工厂模式都是为了创建多类型对象所使用的一种设计方法,在面对上述的 —— 一个类有多种派生子类需要在主体中多次创建使用;判断逻辑较为复杂,需要更加解耦的方式,能够熟练使用反射设计;多种类+多种标准,让人一看就觉得应该用抽象工厂的时候。在设计过程中深思熟虑,不要盲目行事

欢迎关注我、共勉⭐️

⭐️⭐️代码之狐⭐️⭐️
主要内容:

  • 时不时更新算法题解,算法与数据结构
  • 时不时分享心灵鸡汤,详见杂谈栏
  • 目前主要在学Java高级内容(虚拟机、框架什么的),以及很重要的软件工程、重构和设计模式等,会将书中的知识点提炼总结分享