设计模式之工厂模式
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 留言反馈,希望能够帮助到您