为什么要用工厂模式

zqlmianshi / 2024-10-22 / 原文

1.复合开闭原则,对扩展开放,对修改关闭。客户端比如feign调用时,当服务端修改代码后,客户端不需要修改代码。

FactoryBean与工厂方法模式的关系

虽然FactoryBean并不是工厂方法模式的直接实现,但它在某种程度上借鉴了工厂方法模式的思想。FactoryBean通过定义一个接口(FactoryBean接口)和多个实现类(具体FactoryBean实现类)来创建和管理Bean实例,这与工厂方法模式中的抽象工厂接口和具体工厂实现类的关系相似。

然而,FactoryBean在Spring框架中的应用更加广泛和灵活,它不仅限于创建单一类型的Bean实例,还可以进行复杂的逻辑处理和初始化操作。此外,FactoryBean还可以与Spring的其他特性(如依赖注入、AOP等)相结合,实现更加复杂和强大的功能。

综上所述,虽然FactoryBean与工厂方法模式有一定的关联,但它们并不完全相同。FactoryBean是Spring框架中对工厂方法模式的一种应用与扩展,它提供了更加灵活和强大的Bean创建和管理功能。

Java中的工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。以下是对Java工厂方法模式的详细解析:

一、定义与特点

工厂方法模式定义了一个用于创建对象的接口,但让子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行。其主要特点包括:

  1. 抽象工厂角色:声明了工厂方法,用于返回一个产品对象。
  2. 具体工厂角色:实现了抽象工厂角色中的工厂方法,用于返回一个具体的产品对象。
  3. 抽象产品角色:定义了产品的接口,是工厂方法所创建对象的超类型,也就是产品对象的共同接口。
  4. 具体产品角色:实现了抽象产品角色所定义的接口,由具体工厂角色创建,客户端通过抽象产品角色使用具体产品。

二、结构与实现

工厂方法模式的典型结构包含以下四个主要部分:

  1. 抽象产品类:定义产品的接口,是工厂方法所创建的对象的超类型,即产品对象的共同接口。
  2. 具体产品类:实现了抽象产品类所定义的接口,由具体工厂类创建,客户端通过抽象产品类使用具体产品。
  3. 抽象工厂类:声明了工厂方法,用于返回一个产品对象。它是一个抽象类,通常由Java接口或抽象类实现。
  4. 具体工厂类:实现了抽象工厂类中的工厂方法,用于创建一个具体的产品对象。

在实现时,客户端代码通过抽象工厂类和抽象产品类与具体实现进行解耦,从而可以在不修改客户端代码的情况下更换具体工厂类或具体产品类。

三、优点

  1. 降低耦合度:通过将对象的创建过程集中到一个工厂类中,降低了客户端与具体产品之间的耦合度,使得系统更加灵活和易于维护。
  2. 提高复用性:工厂方法模式通过工厂方法、抽象工厂等方式来创建对象,提高了代码的复用性和可读性。它避免了重复的代码实现,因为对象的创建逻辑被封装在工厂类中,可以在多个地方重用该工厂类的实例或方法。
  3. 符合开闭原则:工厂方法模式支持在不修改已有代码的前提下扩展系统,通过添加新的具体工厂类和具体产品类来实现新的功能。
  4. 隐藏创建细节:工厂方法模式将对象的创建过程封装在工厂类中,对客户端隐藏了对象的创建细节,增强了系统的安全性。

四、缺点

  1. 增加系统复杂性:每增加一个产品,都需要增加一个具体产品类和一个具体工厂类,增加了系统的复杂性。当产品种类较多时,会导致类的数量激增。
  2. 产品族扩展困难:在工厂方法模式中,如果需要增加新的产品族(即一组相关联的产品),需要修改所有的具体工厂类,这在一定程度上影响了系统的扩展性。

五、适用场景

  1. 当一个类不知道它所必须创建的对象的类时。
  2. 当一个类希望由它的子类来指定它所创建的对象时。
  3. 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化时。

六、示例代码

以下是一个简单的工厂方法模式示例代码:

java复制代码
  // 抽象产品角色
  public interface Product {
  void doSomething();
  }
   
  // 具体产品A
  public class ProductA implements Product {
  @Override
  public void doSomething() {
  System.out.println("A do Something");
  }
  }
   
  // 具体产品B
  public class ProductB implements Product {
  @Override
  public void doSomething() {
  System.out.println("B do Something");
  }
  }
   
  // 抽象工厂角色
  public abstract class Factory {
  abstract Product create();
  }
   
  // 具体工厂A
  public class FactoryA extends Factory {
  @Override
  Product create() {
  return new ProductA();
  }
  }
   
  // 具体工厂B
  public class FactoryB extends Factory {
  @Override
  Product create() {
  return new ProductB();
  }
  }
   
  // 客户端代码
  public class Client {
  public static void main(String[] args) {
  Factory factory = new FactoryA();
  Product product = factory.create();
  product.doSomething();
   
  factory = new FactoryB();
  product = factory.create();
  product.doSomething();
  }
  }

在这个示例中,Product是抽象产品角色,ProductAProductB是具体产品角色,Factory是抽象工厂角色,FactoryAFactoryB是具体工厂角色。客户端代码通过调用具体工厂类的create方法来创建具体的产品对象,并调用产品的doSomething方法。

综上所述,Java工厂方法模式是一种强大的设计工具,可以帮助开发者构建更加灵活、可扩展和易于维护的软件系统。通过合理地使用工厂方法模式,可以提高代码的质量、可维护性和可复用性。

如果不使用工厂方法模式创建对象,而是手动创建,代码的结构会相对简单,但可能会失去工厂方法模式带来的灵活性和可扩展性。以下是一个不使用工厂方法模式,而是直接手动创建对象的示例代码:

java复制代码
  // 产品接口或抽象类
  public interface Product {
  void doSomething();
  }
   
  // 具体产品A
  public class ProductA implements Product {
  @Override
  public void doSomething() {
  System.out.println("ProductA is doing something.");
  }
  }
   
  // 具体产品B
  public class ProductB implements Product {
  @Override
  public void doSomething() {
  System.out.println("ProductB is doing something.");
  }
  }
   
  // 客户端代码
  public class Client {
  public static void main(String[] args) {
  // 手动创建ProductA对象
  Product productA = new ProductA();
  productA.doSomething();
   
  // 手动创建ProductB对象
  Product productB = new ProductB();
  productB.doSomething();
   
  // 如果需要更多的产品类型,继续手动创建
  // ...
  }
  }

在这个示例中,Product接口定义了一个产品应该具有的行为,ProductAProductB是实现了该接口的具体产品。客户端代码Client中直接使用了new关键字来创建ProductAProductB的实例,并调用了它们的方法。

与工厂方法模式相比,这种手动创建对象的方式有以下几个缺点:

  1. 代码耦合度高:客户端代码直接依赖于具体的产品类,如果产品类发生变化(比如类名、包名或构造方法),客户端代码也需要相应地进行修改。

  2. 扩展性差:如果系统中需要添加新的产品类型,客户端代码需要修改以包含新的产品创建逻辑,这违反了开闭原则(对扩展开放,对修改关闭)。

  3. 缺乏灵活性:客户端代码在编译时就确定了要创建的对象类型,无法在运行时动态地选择创建哪种类型的产品。

因此,虽然手动创建对象的方式在代码上看起来更简单,但在大型系统中,使用工厂方法模式或其他创建型设计模式通常能够带来更好的代码结构、更高的灵活性和可扩展性。