1、概述

  • 在面向对象编程中,创建对象实例最常用的方式就是通过 new 操作符构造一个对象实例,但在某些情况下,new 操作符直接生成对象会存在一些问题。举例来说,对象的创建需要一系列的步骤:可能需要计算或取得对象的初始位置、选择生成哪个子对象实例、或在生成之前必须先生成一些辅助对象。 在这些情况,新对象的建立就是一个 “过程”,而不仅仅是一个操作,就像一部大机器中的一个齿轮传动。
  • 针对上面这种情况,我们如何轻松方便地构造对象实例,而不必关心构造对象示例的细节和复杂过程?解决方案就是使用一个工厂类来创建对象。
  • 工厂模式有三种方式

    • 普通工厂模式
    • 工厂方法模式
    • 抽象工厂模式

      2、普通工厂模式

  • 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。

  • 通过专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。

    2-1、基本使用

  • 抽象产品类:Fruit.java

  • 具体产品类:Apple.java、Banana.java ```java public interface Fruit { void eat(); }

public class Apple implements Fruit{ @Override public void eat() { System.out.println(“吃苹果”); } }

public class Banana implements Fruit{ @Override public void eat() { System.out.println(“吃香蕉”); } }

  1. - FruitFactory.java
  2. ```java
  3. public class FruitFactory {
  4. public static Fruit createFruit(String name){
  5. if ("apple".equals(name)){
  6. return new Apple();
  7. }else if ("banana".equals(name)){
  8. return new Banana();
  9. }
  10. return null;
  11. }
  12. }
  • 测试代码

    1. public class Main {
    2. public static void main(String[] args) {
    3. Fruit apple = FruitFactory.createFruit("apple");
    4. apple.eat();
    5. Fruit banana = FruitFactory.createFruit("banana");
    6. banana.eat();
    7. }
    8. }

    2-2、进阶用法

  • 反射实例类

    1. public class FruitFactory {
    2. public static Fruit createFruit(String name) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    3. Class fruit = Class.forName(name);
    4. return (Fruit) fruit.newInstance();
    5. }
    6. }
  • 验证

    1. public class Main {
    2. public static void main(String[] args) {
    3. try {
    4. Fruit apple = FruitFactory.createFruit("com.company.factory.Apple");
    5. apple.eat();
    6. Fruit banana = FruitFactory.createFruit("com.company.factory.Banana");
    7. banana.eat();
    8. } catch (ClassNotFoundException e) {
    9. e.printStackTrace();
    10. } catch (InstantiationException e) {
    11. e.printStackTrace();
    12. } catch (IllegalAccessException e) {
    13. e.printStackTrace();
    14. }
    15. }
    16. }

    2-3、优缺点

  • 简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

  • 但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

    3、工厂方法模式

    3-1、四个角色

  • 抽象工厂角色:1个,工厂方法模式的核心,创建产品的类必须实现该接口

  • 具体工厂角色:多个,该角色实现了抽象工厂接口,具体如何创建产品就是在该类中实现
  • 抽象产品角色:1个,所有产品的超类,负责实现产品共性的抽象定义
  • 具体产品角色:多个,该角色实现了抽象产品接口,负责具体不同产品的业务逻辑

    3-2、代码示例

  • 抽象工厂、具体工厂 ```java public interface FruitFactory {

    Fruit createFruit(); }

public class BananaFactory implements FruitFactory{

  1. @Override
  2. public Fruit createFruit() {
  3. return new Banana();
  4. }

}

public class AppleFactory implements FruitFactory{ @Override public Fruit createFruit() { return new Apple(); } }

  1. - 使用
  2. ```java
  3. public class Main {
  4. public static void main(String[] args) {
  5. Fruit apple = new AppleFactory().createFruit();
  6. apple.eat();
  7. Fruit banana = new BananaFactory().createFruit();
  8. banana.eat();
  9. }
  10. }

3-3、优缺点

  • 工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。
  • 但缺点在于,每增加一个产品都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

    4、抽象工厂模式

    4-1、代码示例

  • 多个抽象产品类+多个具体抽象产品类 ``` //发动机以及型号
    public interface Engine {}

public class EngineA implements Engine{
public EngineA(){
System.out.println(“制造—>EngineA”);
}
}
public class EngineB implements Engine{
public EngineB(){
System.out.println(“制造—>EngineB”);
}
}

//空调以及型号
public interface Aircondition {}

public class AirconditionA implements Aircondition{
public AirconditionA(){
System.out.println(“制造—>AirconditionA”);
}
}
public class AirconditionB implements Aircondition{
public AirconditionB(){
System.out.println(“制造—>AirconditionB”);
}
}

  1. - 一个抽象工厂类+多个具体抽象工厂类

//创建工厂的接口
public interface AbstractFactory {
//制造发动机 public Engine createEngine(); //制造空调 public Aircondition createAircondition(); }

//为宝马320系列生产配件
public class FactoryBMW320 implements AbstractFactory{
@Override
public Engine createEngine() {
return new EngineA();
}
@Override
public Aircondition createAircondition() {
return new AirconditionA();
}
}
//宝马523系列 public class FactoryBMW523 implements AbstractFactory {
@Override
public Engine createEngine() {
return new EngineB();
}
@Override
public Aircondition createAircondition() {
return new AirconditionB();
}
} ```

4-2、工厂方法模式 VS 抽象工厂模式

  • 工厂方法模式只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。
  • 抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例