当前位置: 首页 > news >正文

快速理解工厂方法模式,及其在源码中的应用

(一)、什么是工厂方法模式

有一个总工厂负责生产各种电视产品,此时来了一个生产小米电视的需求,就会分配出一个制作小米电视的工厂,然后就能用该工厂生产小米电视了。
上面这种通过工厂来实例化类的方式抽象到设计模式中就是工厂方法模式。

(二)、工厂方法模式中的角色

工厂方法模式中有四种角色,理解这四种角色就能理解工厂方法模式。

抽象工厂(Factory):也就是开题这个例子中的总工厂,抽象工厂是所有具体工厂的基类,在抽象工厂角色中,声明了生成产品实例的方法。抽象工厂的目的是为了让实例的生成不再通过new,而是通过生成实例的专用方法

具体工厂(ConcreteFactory):也就是开题这个例子中的制作小米电视的工厂,是抽象工厂的子类,实现抽象工厂中定义的生成产品实例的方法。

抽象产品(Product):也就是开题这个例子中的电视产品,是一个总的抽象产品,定义了一个产品的一系列方法。

具体产品(ConcreteProduct):也就是开题这个例子中的小米电视,是一个具体的产品,实现抽象产品的方法。

(三)、工厂方法模式代码案例

下面的代码描述的是工厂方法模式的案例,实现本文第一章的场景
抽象电视工厂类,提供一个produceTv的抽象方法。

public abstract class TvFactory {
    public abstract Television produceTv();
}

抽象电视产品类,提供一个show方法。

public abstract class Television {
    public abstract void show();
}

具体的电视产品小米电视:

public class XiaomiTelevision extends Television{
    @Override
    public void show() {
        System.out.println("用小米电视看视频");
    }
}

具体工厂:用于生产小米电视:

public class XiaomiTvFactory extends TvFactory{
    @Override
    public Television produceTv() {
        System.out.println("制造了小米电视");
        return new XiaomiTelevision();
    }
}

最后写个测试方法:

public class Main {
    public static void main(String[] args) {
        Television XiaomiTelevision = new XiaomiTvFactory().produceTv();
        XiaomiTelevision.show();
    }
}

这个时候又来了一个华为电视的需求,只需要和生产小米电视一样,生成华为电视具体工厂和华为电视具体类就可以了,如下:

public class HuaweiTvFactory extends TvFactory{
    @Override
    public Television produceTv() {
        System.out.println("制造了一台华为电视");
        return new HuaweiTelevision();
    }
}
public class HuaweiTelevision extends Television{
    @Override
    public void show() {
        System.out.println("使用华为电视看视频");
    }
}

然后就可以使用了

public class Main {
    public static void main(String[] args) {
        Television XiaomiTelevision = new XiaomiTvFactory().produceTv();
        XiaomiTelevision.show();
        Television HuaweiTelevision = new HuaweiTvFactory().produceTv();
        HuaweiTelevision.show();
    }
}

(四)、为什么要用工厂方法模式

从上面的例子也能看出来,使用工厂方法模式后代码变得更加复杂了,并且想在项目中应用上貌似很困难。但是工厂方法模式却能带来一些不一样的东西

1、良好的扩展性

在设计一个项目的时候,首先要设计的是整体的代码架构。设计了顶层的抽象工厂和抽象产品之后,后续有其他的底层实现时,也只需要新增一个继承了抽象工厂的具体工厂类就行。

2、良好的封装性

以前创建一个类需要通过new方法创建,有了工厂类之后,创建的这个动作就交给工厂类去实现类。假设创建一个类的过程很复杂,有许多额外的逻辑,那么这些逻辑只需要在工厂类中实现一次,具体的产品都可以通过工厂类直接获取到。减少模块间的耦合。

3、框架和实现的隔离性

我们可以把抽象工厂和抽象产品定义为框架,而具体工厂和具体产品是实现。通过工厂方法模式,框架和实现之间是分离的。实现了底层的修改不会导致上层的改动。

(五)、工厂方法模式在源码中的应用

我们来看一下slf4j中是如何应用工厂方法模式的:

首先slf4j定义一个抽象工厂ILoggerFactory

public interface ILoggerFactory {
    Logger getLogger(String var1);
}

接着定义了一个抽象产品Logger:

public interface Logger {
    ... ...
}

具体工厂有很多,都实现了抽象工厂,这里展示其中一个SubstituteLoggerFactory

具体工厂用于生产具体的产品,SubstituteLogger就是一种具体的产品,从上边的代码中就可以看到,SubstituteLoggerFactory工厂在生产SubstituteLogger具体产品时,做了一定的处理。而真正使用时,只需要通过getLogger方法就可以得到具体产品,这就是工厂方法模式的魅力。

(六)总结

工厂方法模式相比于适配器模式、迭代器模式或者模板方法模式更加难理解,也更加难应用到项目中。但是我们依旧可以从中学到设计的魅力,学到接口、抽象类存在的目的。

相关文章:

  • 线上报了内存溢出异常,又不完全是内存溢出
  • 用代码告诉你“问世间情为何物,直教人生死相许”
  • 互联网公司的完整开发流程是怎样的?
  • 如何在SpringBoot启动时执行初始化操作,两个简单接口就可以实现
  • BZOJ4584 : [Apio2016]赛艇
  • 查准考证网站卡了整整一个小时进不去,被抢票支配的恐惧又来了
  • 【C#公共帮助类】 ToolsHelper帮助类
  • 这次终于把Spring的监听器讲明白了
  • jquery ajax分页 js对象
  • 详解单例模式及其在Sping中的最优实践
  • Magento Shell
  • 深入了解ElasticSearch的Nested数据类型
  • Python3发送post请求,自动记住cookie
  • 基于SpringCloudGateway实现微服务网关
  • .NET框架
  • JS 中的深拷贝与浅拷贝
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Consul Config 使用Git做版本控制的实现
  • CSS 提示工具(Tooltip)
  • Leetcode 27 Remove Element
  • log4j2输出到kafka
  • PHP 7 修改了什么呢 -- 2
  • 阿里云Kubernetes容器服务上体验Knative
  • 京东美团研发面经
  • 你不可错过的前端面试题(一)
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 如何用纯 CSS 创作一个货车 loader
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​Linux·i2c驱动架构​
  • # Maven错误Error executing Maven
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (4.10~4.16)
  • (八)Spring源码解析:Spring MVC
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (力扣)1314.矩阵区域和
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (转)mysql使用Navicat 导出和导入数据库
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .Net的DataSet直接与SQL2005交互
  • .NET开发者必备的11款免费工具
  • .NET面试题解析(11)-SQL语言基础及数据库基本原理
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • ;号自动换行
  • @31省区市高考时间表来了,祝考试成功
  • @Responsebody与@RequestBody
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [C++从入门到精通] 14.虚函数、纯虚函数和虚析构(virtual)
  • [C语言][PTA基础C基础题目集] strtok 函数的理解与应用