• 工厂模式


    概述

            工厂模式(Factory Pattern)属于创建型模式。

            在工厂模式中,创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

            如果需要创建一个对象,最简单的方式就是直接 new 一个。而工厂模式代替了传统的直接 new 的形式,那么为什么要替代呢?如果所有的对象都通过 new 的方式去创建,那么当程序中大量使用此对象时,突然有一天这个对象的构造方法或是类名发生了修改,那就得逐个去进行修改。

            根据迪米特法则,应该尽可能地少与其他类进行交互,所以可以将那些需要频繁出现的对象创建,封装到一个工厂类中。当需要对象时,直接调用工厂类中的工厂方法来生成对象,这样,就算类出现了变动,只需要修改工厂中的代码即可,而不是大面积地进行修改。同时,可能某些对象的创建并不只是一个 new 就可以搞定,可能还需要更多的步骤来准备构造方法需要的参数。

    核心本质

    • 实例化对象不使用new,用工厂方法代替
    • 将选择实现类,创建对象同意管理和控制。从而将调用者跟我们的实现类解耦

    设计原则

    • 开放封闭原则:一个软件的实体应当对扩展开发,对修改关闭
    • 依赖倒转原则:要针对接口编程,不要针对实现编程
    • 迪米特法则:只与你直接的朋友通信,二避免和陌生人通信

    应用场景

    • 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
    • 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时
    • Spring中IOC容器创建管理bean对象
    • 反射中Class对象的newInstance方法
    • 设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口

    简单工厂模式

            以汽车工厂生产汽车为例介绍简单工厂模式

            1.定义汽车(接口)

    1. public interface Car {
    2. void name();
    3. }

            2.定义BMW类

    1. public class BMW implements Car{
    2. @Override
    3. public void name() {
    4. System.out.println("宝马");
    5. }
    6. }

            3.定义Audi类

    1. public class Audi implements Car{
    2. @Override
    3. public void name() {
    4. System.out.println("奥迪");
    5. }
    6. }

            4.定义汽车工厂

    1. //简单工厂模式(静态工厂模式)
    2. //增加一个新产品,如果不修改代码做不到
    3. //开发封闭原则
    4. public class CarFactory {
    5. //方法一
    6. public static Car getCar(String car){
    7. if(car.equals("宝马")){
    8. return new BMW();
    9. }else if (car.equals("奥迪")){
    10. return new Audi();
    11. }else {
    12. return null;
    13. }
    14. }
    15. //方法二
    16. public static Car getBMW(){
    17. return new BMW();
    18. }
    19. public static Car getAudi(){
    20. return new Audi();
    21. }
    22. }

            5.顾客(调用)

    1. public class Consumer {
    2. public static void main(String[] args) {
    3. //接口实现所有类!工厂
    4. // Car car1 = new BMW();
    5. // Car car2 = new Audi();
    6. //使用工厂创建
    7. Car car1 = CarFactory.getCar("宝马");
    8. Car car2 = CarFactory.getCar("奥迪");
    9. car1.name();
    10. car2.name();
    11. }
    12. }

            不过这样还是有一些问题,前面提到了开闭原则,一个软件实体,比如类、模块和函数应该对扩展开放,对修改关闭。

            此时如果需要新增一种汽车,比如保时捷,那么就得去修改工厂提供的工厂方法了,这样是不太符合开闭原则的。因为工厂实际上是针对于调用方提供的,所以应该尽可能对修改关闭。

    工厂方法模式

            所以,我们就利用对扩展开放,对修改关闭的性质,将简单工厂模式改进为工厂方法模式,既然不让改,那么就看看如何去使用扩展的形式。

            这里还是以汽车工厂生产汽车介绍工厂方法模式(在简单工厂模式上修改):

            1.定义汽车工厂

    1. public interface CarFactory {
    2. Car getCar();
    3. }

            2.定义BMW工厂

    1. public class BMWFactory implements CarFactory{
    2. @Override
    3. public Car getCar() {
    4. return new BMW();
    5. }
    6. }

            3.定义Audi工厂

    1. public class AudiFactory implements CarFactory{
    2. @Override
    3. public Car getCar() {
    4. return new Audi();
    5. }
    6. }

            4.增加Tesla

                ①定义Tesla类

    1. public class Tesla implements Car{
    2. @Override
    3. public void name() {
    4. System.out.println("特斯拉");
    5. }
    6. }

                ②定义Tesla工厂

    1. public class TeslaFactory implements CarFactory{
    2. @Override
    3. public Car getCar() {
    4. return new Tesla();
    5. }
    6. }

            这样,就可以使用不同类型的工厂来生产不同类型的汽车了,如果新增了汽车类型,直接创建一个新的工厂类就行,不需要修改之前已经编写好的内容。

            5.顾客(调用)

    1. public class Consumer {
    2. public static void main(String[] args) {
    3. Car car1 = new BMWFactory().getCar();
    4. Car car2 = new AudiFactory().getCar();
    5. Car car3 = new TeslaFactory().getCar();
    6. car1.name();
    7. car2.name();
    8. car3.name();
    9. }
    10. }

            这样,就简单实现了工厂方法模式,通过工厂来屏蔽对象的创建细节,使用者只需要关心如何去使用对象即可。

    小结

    • 简单工厂模式:虽然某种程度上不符合设计原则,但实际使用最多
    • 工厂方法模式:在不修改已有类的前提下,通过增加新的工厂类实现扩展

    优缺点

    优点

    • 一个调用者想创建一个对象,只要知道其名称就可以了
    • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以
    • 屏蔽产品的具体实现,调用者只关心产品的接口

    缺点

            每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖

    注意事项

            作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

  • 相关阅读:
    红胖子创业一年整总结:前二十年题记,萌芽初期,外包初期,创业初期,未来规划
    Vue项目中,el-image实现按钮触发大图预览模式
    Cron(Crontab)--使用/教程/实例
    leetcode 21
    深度学习技巧应用28-强化学习的原理介绍与运用技巧实践
    ElasticSearch中的文档和查询响应数据
    图像处理:随机添加椒盐噪声和高斯噪声Python
    给你两个集合,要求{A} + {B}
    以功促防 攻防演练对企业价值-全面提升企业安全性
    【Call for papers】CSFW-2023(CCF-B/网络与信息安全/2023年2月3日截稿)
  • 原文地址:https://blog.csdn.net/weixin_48426115/article/details/127838711