当前位置:   article > 正文

设计模式之工厂模式

设计模式之工厂模式

工厂模式是一种创建型设计模式,其核心思想是定义一个创建对象的接口(即工厂),让子类决定实例化哪一个类。工厂模式将对象的创建与使用分离,使代码更易于维护和扩展,尤其在需要根据条件动态创建不同类的实例时非常有用。

工厂模式主要有以下三种形态:

简单工厂模式(Simple Factory)

工厂方法模式(Factory Method)

抽象工厂模式(Abstract Factory)

1、简单工厂模式(Simple Factory)

  • 概念:定义一个工厂类,负责创建某一类对象,客户端通过调用工厂类的静态方法来获取所需对象。简单工厂模式封装了对象的创建过程,隐藏了具体产品的类名,使得客户只需关注产品的接口而非创建细节。
  • 优点:减少客户端与具体产品类之间的耦合,新增产品时只需修改工厂类即可。
  • 缺点:当产品种类较多时,工厂类可能会变得庞大且难以维护;违背开闭原则,增加新产品时需要修改工厂类代码。

Java代码示例:

  1. // 定义产品接口
  2. public interface Product {
  3. void use();
  4. }
  5. // 具体产品A
  6. public class ConcreteProductA implements Product {
  7. @Override
  8. public void use() {
  9. System.out.println("Using product A");
  10. }
  11. }
  12. // 具体产品B
  13. public class ConcreteProductB implements Product {
  14. @Override
  15. public void use() {
  16. System.out.println("Using product B");
  17. }
  18. }
  19. // 工厂类
  20. public class SimpleFactory {
  21. public static Product createProduct(String type) {
  22. if ("A".equals(type)) {
  23. return new ConcreteProductA();
  24. } else if ("B".equals(type)) {
  25. return new ConcreteProductB();
  26. } else {
  27. throw new IllegalArgumentException("Invalid product type");
  28. }
  29. }
  30. }
  31. // 客户端代码
  32. public class Client {
  33. public static void main(String[] args) {
  34. Product productA = SimpleFactory.createProduct("A");
  35. productA.use(); // 输出:Using product A
  36. Product productB = SimpleFactory.createProduct("B");
  37. productB.use(); // 输出:Using product B
  38. }
  39. }

2、工厂方法模式(Factory Method)

  • 概念:定义一个用于创建对象的抽象工厂接口(或抽象类),并让子类决定实例化哪一个产品类。工厂方法模式将简单工厂的静态方法改为抽象方法,让子类去实现具体的对象创建。
  • 优点:符合开闭原则,新增产品时只需增加新的工厂子类,无需修改原有代码;支持多态,子类可以覆盖基类的方法以提供不同类型的对象。
  • 缺点:类的层级结构可能会变得复杂,特别是产品类型较多时。

Java代码示例:

  1. // 定义产品接口
  2. public interface Product {
  3. void use();
  4. }
  5. // 具体产品A
  6. public class ConcreteProductA implements Product {
  7. @Override
  8. public void use() {
  9. System.out.println("Using product A");
  10. }
  11. }
  12. // 具体产品B
  13. public class ConcreteProductB implements Product {
  14. @Override
  15. public void use() {
  16. System.out.println("Using product B");
  17. }
  18. }
  19. // 抽象工厂接口
  20. public interface Factory {
  21. Product createProduct();
  22. }
  23. // 具体工厂A
  24. public class ConcreteFactoryA implements Factory {
  25. @Override
  26. public Product createProduct() {
  27. return new ConcreteProductA();
  28. }
  29. }
  30. // 具体工厂B
  31. public class ConcreteFactoryB implements Factory {
  32. @Override
  33. public Product createProduct() {
  34. return new ConcreteProductB();
  35. }
  36. }
  37. // 客户端代码
  38. public class Client {
  39. public static void main(String[] args) {
  40. Factory factoryA = new ConcreteFactoryA();
  41. Product productA = factoryA.createProduct();
  42. productA.use(); // 输出:Using product A
  43. Factory factoryB = new ConcreteFactoryB();
  44. Product productB = factoryB.createProduct();
  45. productB.use(); // 输出:Using product B
  46. }
  47. }

3、抽象工厂模式(Abstract Factory)

  • 概念:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式为创建一组产品族提供了一个接口,而具体的产品族创建由具体工厂子类实现。
  • 优点:隔离了具体产品类的使用,使得客户端只需与抽象产品和抽象工厂交互;支持产品族的切换,只需改变具体工厂的实例即可。
  • 缺点:增加了系统的复杂性,尤其是产品族中产品类数量较多时;新增产品族时需要修改抽象工厂接口及其实现类。

Java代码示例:

  1. // 定义产品接口
  2. public interface ProductA {
  3. void useA();
  4. }
  5. public interface ProductB {
  6. void useB();
  7. }
  8. // 具体产品A1
  9. public class ConcreteProductA1 implements ProductA {
  10. @Override
  11. public void useA() {
  12. System.out.println("Using product A1");
  13. }
  14. }
  15. // 具体产品B1
  16. public class ConcreteProductB1 implements ProductB {
  17. @Override
  18. public void useB() {
  19. System.out.println("Using product B1");
  20. }
  21. }
  22. // 具体产品A2
  23. public class ConcreteProductA2 implements ProductA {
  24. @Override
  25. public void useA() {
  26. System.out.println("Using product A2");
  27. }
  28. }
  29. // 具体产品B2
  30. public class ConcreteProductB2 implements ProductB {
  31. @Override
  32. public void useB() {
  33. System.out.println("Using product B2");
  34. }
  35. }
  36. // 抽象工厂接口
  37. public interface AbstractFactory {
  38. ProductA createProductA();
  39. ProductB createProductB();
  40. }
  41. // 具体工厂1
  42. public class ConcreteFactory1 implements AbstractFactory {
  43. @Override
  44. public ProductA createProductA() {
  45. return new ConcreteProductA1();
  46. }
  47. @Override
  48. public ProductB createProductB() {
  49. return new ConcreteProductB1();
  50. }
  51. }
  52. // 具体工厂2
  53. public class ConcreteFactory2 implements AbstractFactory {
  54. @Override
  55. public ProductA createProductA() {
  56. return new ConcreteProductA2();
  57. }
  58. @Override
  59. public ProductB createProductB() {
  60. return new ConcreteProductB2();
  61. }
  62. }
  63. // 客户端代码
  64. public class Client {
  65. public static void main(String[] args) {
  66. AbstractFactory factory1 = new ConcreteFactory1();
  67. ProductA productA1 = factory1.createProductA();
  68. productA1.useA(); // 输出:Using product A1
  69. ProductB productB1 = factory1.createProductB();
  70. productB1.useB(); // 输出:Using product B1
  71. AbstractFactory factory2 = new ConcreteFactory2();
  72. ProductA productA2 = factory2.createProductA();
  73. productA2.useA(); // 输出:Using product A2
  74. ProductB productB2 = factory2.createProductB();
  75. productB2.useB(); // 输出:Using product B2
  76. }
  77. }

使用中需要注意的问题:

  1. 明确工厂职责

    • 确保工厂类或方法专注于对象创建,避免承担过多业务逻辑,保持其单一职责。如果工厂过于复杂,可能需要进一步抽象或拆分为多个工厂。
    • 对于工厂方法模式和抽象工厂模式,要清晰划分工厂接口与具体工厂类的责任,确保接口的通用性和具体工厂类的可扩展性。
  2. 遵守开闭原则

    • 工厂模式的设计应遵循开闭原则,即对扩展开放,对修改关闭。新增产品时,应通过增加新的工厂类(工厂方法模式)或新的具体工厂子类(抽象工厂模式),而不是修改已有工厂类的代码。
    • 对于简单工厂模式,虽然直接修改工厂类会导致违反开闭原则,但在简单场景下,或者产品种类较少、不易变动时,仍不失为一种实用的选择。如果预计产品种类会频繁增加或变动,建议使用工厂方法或抽象工厂模式。
  3. 处理依赖关系

    • 如果产品类之间存在复杂的依赖关系,或者需要一起创建一组相关对象,应考虑使用抽象工厂模式,它能更好地管理产品族的创建。
    • 对于简单工厂或工厂方法模式,如果产品类的依赖关系比较简单,可以直接在工厂中创建或注入依赖。如果依赖关系较复杂,可能需要配合依赖注入框架或服务定位器模式来管理。
  4. 控制类的个数

    • 工厂模式可能会增加类的数量,特别是在产品种类较多时。应合理规划类结构,避免类爆炸。可以通过模块化、分包等方式组织代码,提高可读性和可维护性。
    • 对于简单工厂模式,如果产品种类过多导致工厂类庞大,可以考虑使用策略模式或枚举类等方式替代部分简单工厂功能。
  5. 考虑使用场景

    • 工厂模式并非所有情况下的首选解决方案。对于简单对象的创建,直接使用构造函数或静态工厂方法可能更为简洁。只有在对象创建逻辑复杂、需要动态决定创建何种对象,或者希望将对象创建细节与使用分离时,才应考虑使用工厂模式。
  6. 测试与调试

    • 工厂模式可能会增加代码的复杂性,影响测试的便利性。应确保工厂类及其创建的产品类具有良好的可测试性,如提供适当的构造函数、依赖注入点或模拟接口,以便于单元测试。
    • 调试时,注意跟踪工厂创建对象的过程,特别是涉及多层工厂或工厂链时,确保对象的创建路径符合预期。
  7. 代码复用与扩展

    • 如果多个工厂有相似的创建逻辑,可以考虑提取公共部分到基类或工具类中,避免代码重复。
    • 在设计工厂接口时,要考虑未来的扩展性,确保接口定义能够适应潜在的新产品类型。
  8. 性能与资源管理

    • 如果工厂模式用于创建资源密集型对象(如数据库连接、文件句柄等),需要考虑资源的有效管理和回收,避免资源泄露。
    • 对于工厂方法模式,如果工厂类实例化成本较高,可以考虑使用单例模式或享元模式来优化。

总结来说,使用工厂模式时,应关注职责划分、开闭原则的遵循、依赖关系管理、类数量控制、使用场景选择、测试与调试的便利性、代码复用与扩展性以及性能与资源管理等方面的问题,以确保模式的有效运用和系统的健壮性。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/488449
推荐阅读
相关标签
  

闽ICP备14008679号