23种设计模式——2.工厂方法模式3.抽象工厂模式

概念

首先,我们理解工厂模式。就是将创建对象的过程封装到工厂类中,实现创建对象与使用的解耦。

这种方法,映射到实际应用中:我们作为消费者,如果要使用汽车,并不是自己创造一个,而是找汽车工厂,告诉它。调用汽车工程的造汽车方法。

根据抽象类型的不同,可以分为3种:

  • 简单工厂模式 ❎(不符合开闭原则)

  • 工厂方法模式

  • 抽象工厂模式

    工厂模式和抽象工厂模式适用范围如下:

    维度 工厂方法模式 抽象工厂模式
    扩展方向 垂直扩展(单一产品类型) 水平扩展(多产品族组合)
    复杂度 较低(仅需维护一层工厂) 较高(需管理多维产品组合)
    适用场景复杂度 简单对象创建场景47 复杂对象依赖场景
    类数量 随产品类型线性增长 随产品族规模指数增长

使用

接下来的例子,假设水果工厂,消费者会根据需要,让水果工厂生成不同的水果。

水果的抽象方法和类如下:

/**
 * 水果抽象类
 * @Author:lyj
 * @Date:2025/5/4 15:42
 */
public abstract  class Fruit {
    private final String name;
    public Fruit(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name + "@" + hashCode();
    }
}
/**
 * 苹果类
 * @Author:lyj
 * @Date:2025/5/4 15:44
 */
public class Apple extends Fruit{
    public Apple() {
        super("苹果");
    }
}
/**
 * 梨
 * @Author:lyj
 * @Date:2025/5/4 15:45
 */
public class Pear extends Fruit {
    public Pear()
    {
        super("梨");
    }
}

简单工厂模式

简单工厂模式,直接创建静态方法。根据输入的值,创建不同的方法。

/**
 * 简单工厂模式(不推荐)
 * @Author:lyj
 * @Filename:SimpleFactory
 */
public class SimpleFactory {
    /**
     * 直接创建一个静态方法,根据类型进行创建对象
     * @param name
     * @return
     */
    public static Fruit getFruit(String name)
    {
        switch(name) {
            case "苹果":
                return new Apple();
            case "梨":
                return new Pear();
            default:
                return null;
        }
    }
}

这种方法虽然简单明了,不符合开闭原则。如果新增一个水果,比如樱桃,那么阁下需要修改静态方法。总之,需要为每一个类,逐一添加方法。

工厂方法模式 ✔️

如果新增了水果类型,直接创建新的工厂即可,不需要修改之前已经编写好的代码。

/**
 * 工厂方法
 * @Author:lyj
 * @Date:2025/5/4 16:02
 */
public abstract class MyFactory<T extends Fruit> {
    public abstract T getFruit();
}
/**
 * 苹果工厂
 */
public class AppleFactory extends MyFactory<Apple> {
    @Override
    public Apple getFruit()
    {
        return new Apple();
    }
}
/**
 * 梨工厂
 * @Author:lyj
 * @Date:2025/5/4 16:05
 */
public class PearFactory extends MyFactory<Pear>{
    @Override
    public Pear getFruit() {
        return new Pear();
    }
}

使用时,需要那种水果,就找对应的工厂:

Fruit fruit = new AppleFactory().getFruit();
System.out.println(fruit);

不过,一种水果创建一个工厂类,工厂类太多了。

抽象工厂模式

抽象工厂模式,提供一个接口,用于创建相关或依赖家族对象,无需指定具体类。

核心角色:

  • 抽象工厂(AbstractFactory) :声明创建产品族的方法

  • 具体工厂(ConcreteFactory) : 实现抽象工厂,生产统一主题的多个产品。

  • 抽象产品(Product) : 定义产品接口(通常多个)

  • 具体产品(ConcreterProduct) : 统一主题下的多个具体产品。

    抽象模式适合不同的相似的工厂,创建相关联的产品族。例如UI风格(文本框、复选框……),电子产品(不同生产商生产的手机)。下面还是以水果为例。产品如下:

   /**
    * 抽象类:苹果
   * @Author:lyj
   * @Date:2025/5/5  10:55
   */public interface Apple {
       // 水果生长
       void grow();
   }
   /**
    * 具体产品:苹果1
    * @Author:lyj
    * @Date:2025/5/5 10:57
    */
   public class Apple1 implements Apple {
       @Override
       public void grow() {
           System.out.println("红富士苹果");
       }
   }
   
   /**
    * 具体产品:苹果2
    * @Author:lyj
    * @Date:2025/5/5 10:58
    */
   public class Apple2 implements Apple{
       @Override
       public void grow() {
           System.out.println("嘎啦果");
       }
   }
   /**
    * 抽象产品 : 梨
    * @Author:lyj
    * @Date:2025/5/5 11:00
    */
   public interface Pear {
       // 打包水果
       void pack();
   }
   /**
    * 具体产品:梨1
    * @Author:lyj
    * @Date:2025/5/5 11:01
    */
   public class Pear1 implements Pear {
       @Override
       public void pack() {
           System.out.println("皇冠梨");
       }
   }
   /**
    * 具体类:梨2
    * @Author:lyj
    * @Date:2025/5/5 11:04
    */
   public class Pear2 implements Pear {
       @Override
       public void pack() {
           System.out.println("库尔勒香梨");
       }
   }

工厂方法如下:

   /**
    * 抽象产品:水果工厂 (抽象工厂类)
    * @Author:lyj
    * @Date:2025/5/5 10:37
    */
   public interface FruitFactory {
       Apple createApple();
       Pear createPear();
   }
   /**
    * 具体工厂: 水果工厂1
    * @Author:lyj
    * @Date:2025/5/5 11:12
    */
   public class FruitFactory1 implements FruitFactory{
   
       @Override
       public Apple createApple() {
           return new Apple1();
       }
   
       @Override
       public Pear createPear() {
           return new Pear1();
       }
   }
   /**
    * 具体工厂:水果工厂2
    * @Author:lyj
    * @Date:2025/5/5 11:14
    */
   public class FruitFactory2 implements FruitFactory{
       @Override
       public Apple createApple() {
           return new Apple2();
       }
   
       @Override
       public Pear createPear() {
           return new Pear2();
       }
   }

抽象工厂调用方法如下:

// 水果工厂1
FruitFactory factory1 = new FruitFactory1();
Apple apple1 = factory1.createApple();
Pear pear1 = factory1.createPear();
apple1.grow();      // 红富士苹果
pear1.pack();       // 皇冠梨
// 水果工厂2
FruitFactory factory2 = new FruitFactory2();
Apple apple2 = factory2.createApple();
Pear pear2 = factory2.createPear();
apple2.grow();      // 嘎啦果
pear2.pack();       // 库尔勒香梨

应用场景

工厂模式和抽象工厂模式区别:

  • 工厂模式 针对单一产品(如按钮或日志器),通过子类决定实例化那个类
  • 抽象工厂模式 针对产品族(如整套UI控件或数据库组件),强调家族内产品的兼容性

工厂模式

  • 图形绘制工具
  • 日志记录系统 (工厂子类分别生成文件日志和控制台日志实例)
  • 数据库连接管理 (配置返回MySql 或PostgreSQL 的连接对象)

抽象工厂模式

  • 跨平台UI组件库 , 不同平台生成不同风格的控件
  • 操作系统兼容新工具 ,为WIndows和Linux分别提供文件操作和进程管理组件
  • 服装品牌生产线 , NikeFactory 生产运动鞋和T恤,AdidasFactory 生产跑鞋和卫衣
posted @ 2025-06-20 15:17  陆陆无为而治者  阅读(29)  评论(0)    收藏  举报