设计模式之工厂模式

设计模式之工厂模式

0 概述

  • 工厂模式是一种创建型设计模式,用于创建对象而无需指定明确的类。它将对象的创建委托给一个工厂类,该类根据输入参数来决定要实例化的类。这样做可以使代码更具灵活性和可维护性。
  • 工厂模式主要分为三种:
    • 简单工厂:由一个工厂类根据传入的参数决定创建哪一种产品类的实例。
    • 工厂方法:定义一个创建对象的接口,但由子类决定要实例化的类。每个子类都可以实例化特定类型的对象。
    • 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

1 使用场景

  • 工厂模式通常在以下情况下使用:
    • 当一个类不知道它必须创建的对象的类时。将创建对象的责任委托给工厂类,由工厂类根据条件或参数来创建对应的对象。(可以列举线程池的源码举例)
    • 当一个类希望由其子类来决定创建哪个对象时。通过定义一个创建对象的接口,在子类中实现具体的对象创建方法,从而实现对象的创建过程的变化。
    • 当类中有大量重复的代码,需要通过工厂方法来消除重复代码。

2 优缺点

  • 优点
    • 解耦性:将对象的创建与使用分离,降低了系统的耦合度。
    • 扩展性:增加了代码的可扩展性,可以方便地添加新的产品类。
    • 简洁性:隐藏了对象的创建细节,使客户端代码更加简洁。
  • 缺点
    • 引入了额外的工厂类,增加了系统的复杂度。
    • 当产品类较多时,可能会导致工厂类过于庞大,不易维护。
    • 每多生产一种对象,就需要改动工厂类里的方法,违背了设计模式中的开闭原则。

      补充说明:开闭原则的核心思想是通过抽象化、封装和多态来实现可扩展和可复用的代码。通过将不同的功能封装在不同的类中,并利用接口或抽象类定义统一的方法,可以实现在不修改原有代码的情况下对功能进行扩展。当需要添加新的功能时,只需要新增一个实现了接口或抽象类的新类,并在原有代码中使用该类的实例即可。

3 代码示例 – 简单工厂 + 工厂方法

  • 创建一个工厂接口

    /**
     * 简单工厂接口
     * 
     * @Author Jasper
     * @Time 2024/02/06
     * @公众号: EzCoding
     */
    public interface MySimpleFactory {
    
        // 生产对象方法
        void produce();
    
    }
    
  • 分别创建【手机】【电脑】【平板】类,并实现自定义的工厂接口

    /**
     * 手机对象
     *
     * @Author Jasper
     * @Time 2024/02/06
     * @公众号:EzCoding
     */
    public class Phone implements MySimpleFactory {
        @Override
        public void produce() {
            System.out.println("生产手机");
        }
    }
    
    /**
     * 电脑对象
     *
     * @Author Jasper
     * @Time 2024/02/06
     * @公众号:EzCoding
     */
    public class Computer implements MySimpleFactory {
        @Override
        public void produce() {
            System.out.println("生产电脑");
        }
    }
    
    /**
     * 平板对象
     *
     * @Author Jasper
     * @Time 2024/02/06
     * @公众号:EzCoding
     */
    public class Pad implements MySimpleFactory {
        @Override
        public void produce() {
            System.out.println("生产平板");
        }
    }
    
  • 创建具体工厂类,定义静态方法,用来生产不同对象

    import cn.hutool.core.util.StrUtil;
    
    /**
     * 这是一个具体工厂,用来生产不同的对象
     *
     * @Author Jasper
     * @Time 2024/02/06
     * @公众号:EzCoding
     */
    public class MethodFactoryImpl {
    
        public static MySimpleFactory produce(String category) {
            if (StrUtil.equals(category, "phone")) {
                return new Phone();
            } else if (StrUtil.equals(category, "computer")) {
                return new Computer();
            } else if (StrUtil.equals(category, "pad")) {
                return new Pad();
            } else {
                return null;
            }
        }
    
    }
    
  • 工厂方法测试类

    /**
     * 工厂方法测试类
     * @Author Jasper
     * @Time 2024/02/06
     * @公众号:EzCoding
     */
    public class SimpleFactoryTest {
    
        public static void main(String[] args) {
            // 通过工厂创建手机对象
            MySimpleFactory phone = MethodFactoryImpl.produce("phone");
            assert phone != null;
            phone.produce();        // 输出:生产手机
    
            // 通过工厂创建电脑对象
            MySimpleFactory computer = MethodFactoryImpl.produce("computer");
            assert computer != null;
            computer.produce();     // 输出:生产电脑
    
            // 通过工厂创建平板对象
            MySimpleFactory pad = MethodFactoryImpl.produce("pad");
            assert pad != null;
            pad.produce();          // 输出:生产平板
        }
    
    }
    

4 代码示例-抽象工厂

  • 定义生产电子产品的工厂

    /**
     * 生产电子产品的工厂
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public interface ElectronicFactory {
        void produce();
    }
    
  • 定义生产衣服的工厂

    /**
     * 生产衣服的工厂
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public interface ClothesFactory {
        void produce();
    }
    
  • 定义抽象工厂

    /**
     * 抽象工厂
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public interface MyAbstractFactory {
    
        // 生产衣服
        ClothesFactory createClothes();
    
        // 生产电子产品
        ElectronicFactory createElectronic();
    
    }
    
  • 衣服类的对象实体

    /**
     * 衣服 - 外套
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class Coat implements ClothesFactory {
        @Override
        public void produce() {
            System.out.println("生产外套");
        }
    }
    
    /**
     * 衣服 - T恤
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class Shirt implements ClothesFactory {
        @Override
        public void produce() {
            System.out.println("生产T恤");
        }
    }
    
  • 电子产品类的对象实体

    /**
     * 电子产品 - 手机
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class Phone implements ElectronicFactory {
        @Override
        public void produce() {
            System.out.println("生产手机");
        }
    }
    
    
    /**
     * 电子产品 - 电脑
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class Computer implements ElectronicFactory {
        @Override
        public void produce() {
            System.out.println("生产电脑");
        }
    }
    
  • 具体工厂实现类1,生产衣服类中的外套、电子类中的手机

    /**
     * 具体工厂1
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class MyFactoryImpl1 implements MyAbstractFactory {
        // 生产 【衣服 - 外套】
        @Override
        public ClothesFactory createClothes() {
            return new Coat();
        }
    
        // 生产 【电子 - 手机】
        @Override
        public ElectronicFactory createElectronic() {
            return new Phone();
        }
    }
    
  • 具体工厂实现类2,生产衣服类中的T恤、电子类中的电脑

    /**
     * 具体工厂2
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class MyFactoryImpl2 implements MyAbstractFactory {
        // 生产 【衣服 - T恤】
        @Override
        public ClothesFactory createClothes() {
            return new Shirt();
        }
    
        // 生产 【电子 - 电脑】
        @Override
        public ElectronicFactory createElectronic() {
            return new Computer();
        }
    }
    
  • 测试类

    /**
     * 抽象工厂测试类
     *
     * @Author Jasper
     * @Time 2024/2/7
     * @公众号:EzCoding
     */
    public class MyFactoryTest {
    
        public static void main(String[] args) {
            MyFactoryImpl1 myFactoryImpl1 = new MyFactoryImpl1();
            // 通过抽象工厂创建对象
            ClothesFactory coat = myFactoryImpl1.createClothes();
            coat.produce();  // 生产外套
            ElectronicFactory phone = myFactoryImpl1.createElectronic();
            phone.produce(); // 生产手机
    
            // 通过抽象工厂创建对象
            MyFactoryImpl2 myFactoryImpl2 = new MyFactoryImpl2();
            ClothesFactory tShirt = myFactoryImpl2.createClothes();
            tShirt.produce();    //生产T恤
            ElectronicFactory computer = myFactoryImpl2.createElectronic();
            computer.produce();  // 生产电脑
        }
    }
    

5 总结

  • 总的来说:

    • 简单工厂创建对象很单一,扩展性不好
    • 工厂方法在同类产品的维度上方便扩展,其本质就是抽象工厂的特例
    • 抽象工厂在不同类的产品族维度上方便扩展
  • 以上就是工厂模式的全部内容了,后续再介绍策略模式

  • 创作不易,感谢阅读,若遇到问题,可以关注此微信gzh:EzCoding 留言反馈,希望能够帮助到您

你可能感兴趣的:(设计模式,java,后端)