工厂模式
设计模式-工厂模式
概念
工厂模式是一种创建性模式,在接口中定义创建对象的方法,将具体的创建对象的过程在子类中实现,用户只需要通过接口创建需要的对象即可,不用关注对象的具体创建过程。
通俗的讲 就是用工厂方法代替new操作创建一个实例化对象的方法,以提供一种方便的创建有同种类型接口的产品的复杂对象。
比如说一个类在创建时候,需要其他类的的信息,直接通过new关键字实例化对象会增加耦合度,不利于维护,直接通过new关键字会增加代码的耦合度,不利于维护,因此需要通过工厂模式将创建实例和使用实例分开。将创建实例的方法封装到工厂方法中,使用时直接调用工厂来进行获取。
按照实际业务场景划分,工厂模式有三种不同的实现方式,分别是:简单工厂模式、工厂方法模式和抽象工厂模式
要分清楚这三者的关系,首先我们先了解两个概念,什么是产品等级?什么是产品族?
产品等级:即有继承结构的同种类的产品,我们称之为产品等级。比如:苹果手机、小米手机。
产品族:一个具体工厂生产的不同等级的一组产品称为一个产品族。比如:小米手机、小米扫地机等。
如果分别用一句话来概括他们,那就是:
1)简单工厂:生产同一产品等级的任意指定的产品。(不支持增加新产品,增加新产品需要修改代码)
2)工厂方法:生产同一产品等级的固定工厂产品。(支持增加新产品)
3)抽象工厂:生产不同产品族的全部产品。(支持增加产品族,但不支持增加新产品)
简单工厂模式
概念:
简单工厂模式也叫静态工厂模式,就是工厂类(一般使用静态方法)通过接收的参数来区分并返回不同的对象实例。
感觉像是一种编程习惯。
结构:
简单工厂包含如下角色:
比亚迪和特斯拉都是能在路上跑的车。
1 | interface Car{ |
在没有工厂的情况下,我们要让比亚迪或者特斯拉出来跑的话。我们会这样写:
1 | public class CarUse { |
此时的调用者(CarUse类)和创建者Byd和Tsl都是有关联的,调用者什么都是亲力亲为。
我们知道,工厂模式就是要分离调用者和创建者。现在我们创建一个简单工厂,由简单工厂类去统一管理创建者。
1 | //写法一 |
虽然我们多写了一个CarFactory工厂类,整体上的代码变多了一点点。但是我们的调用者不必依赖我们的创建者,仅仅需要告诉工厂你要什么,无需知道工厂去哪里帮你实现你的需求,这样调用者就省去了很多的事情。
后来生意做红火了,来了个有钱的客户,这次要买玛莎拉蒂,也就是新产品了。我们的工厂就不适用了,我们的工厂需要找到玛莎拉蒂的实体,然后在我们的工厂上加入新的品牌,不修改代码是无法扩展了。
优缺点
优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。
工厂方法模式:
虽然简单工厂模式解决了调用者和创建者之间的耦合,但是工厂和创建者之间依然存在着耦合。这样的设计违背了我们的“开闭原则”,未来新产品的扩展并不灵活。而“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码(比如工厂类)的情况下引进新的产品,即满足开闭原则。
概念
定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
1 | //声明一个抽象工厂 |
实现
工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式(对于一个项目或者一个独立的模块而言)只有一个工厂类,而工厂方法模式有一组实现了相同接口的工厂类。调用者不是什么都找一个工厂,而是需要什么就找什么工厂提供,这样可选择的范围更大。
现在,我们的新客户要玛莎拉蒂,就可以直接找我们的玛莎拉蒂工厂。我们只需要有新建的玛莎拉蒂工厂即可满足客户的要求。
1 | //新建玛莎拉蒂工厂 |
我们的客户,只需要找到这家玛莎拉蒂工厂即可。
1 | public class CarUse { |
优缺点:
- 优点
1)用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
2)对于新产品的创建,只需多写一个相应的工厂类,不会影响已有的代码,后期维护容易,增强系统的扩展性。
- 缺点
类的个数容易过多,增加系统的复杂度和理解难度。
注:从结构的复杂度、代码的复杂度以及客户端调用者的编程
简单工厂模式和工厂方法模式的比较:
比较维度 | 简单工厂模式 | 工厂方法模式 | 说明 |
---|---|---|---|
结构、代码复杂度 | 优 | 良 | 简单工厂模式占优,只需要一个工厂类,而工厂方法模式会随着工厂的数量增加而增加 |
调用者使用难度 | 优 | 良 | 简单工厂模式的工厂类是静态类,调用者无需实例化 |
扩展性 | 良 | 优 | 工厂方法模式满足OCP原则,具有非常良好的扩展性。简单工厂的扩展性稍弱,但是只要改动不大产品不是特别复杂,简单工厂模式无疑是更优的选择。 |
注:事实上我们有时并不需要像一些框架一样做到那么灵活,反而一般都用简单工厂模式,这样代码简洁逻辑也清晰,可以使用
应用场景:
1)对于产品种类相对较少的情况,考虑使用简单工厂模式;
2)当您想为您的库或框架的用户提供一种扩展其内部组件的方法时,请使用工厂方法模式。
DJK中工厂模式的使用:
1)java.util.Calendar中的getInstance()
方法使用了工厂模式。