抽象工厂模式详解

一、简介

抽象工厂模式(Abstract Factory Pattern)也是一种创建型设计模式,它提供了一种创建一系列相关或者相依赖对象的工厂接口(超级工厂),不同类型的工厂再去实现这个抽象工厂,最后还可提供一个工厂创造者类,通过传入工厂类型参数来创建具体工厂。它是对工厂方法模式的扩展,核心思想是将工厂本身也抽象化,其主旨是围绕一个超级工厂或中心工厂去创建其他工厂,这个超级工厂又称为其他工厂的工厂。

它与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级;而抽象工厂模式则是针对的多个产品等级,即一个产品族。在编程中,通常一个产品等级,表现为一个接口或者抽象类及其下的实现类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

所谓的产品族,是指位于不同产品等级中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品组成一个产品等级。

对比现实生活,一个产品族,如数码产品。一个产品等级,如手机,包括所有品牌的手机都属于这个产品等级,而所有笔记本电脑又是另一个产品等级。所有手机和电脑共同构成数码产品这个产品族。

设计原理

抽象工厂模式通常包含四个必要角色和一个可选角色:

  • 抽象工厂(Abstract Factory):定义一个接口或抽象类,它声明了一组用于创建相关产品对象的方法,这些方法的返回值通常是一个抽象产品。
  • 具体工厂(Concrete Factory):它实现了抽象工厂中声明的创建产品对象的方法,同一产品等级下根据不同的产品参数,创建一个具体产品对象。
  • 抽象产品(Abstract Product):定义一个接口或抽象类,表示同类产品,在抽象产品中声明了产品所具有的方法。
  • 具体产品(Concrete Product):它定义了抽象产品下所拥有的具体产品,实现了抽象产品接口中定义的业务方法。
  • 工厂创造器(可选角色):提供一个静态方法,根据传入不同的工厂类型参数,创造一个具体的工厂类,返回值用抽象工厂接收。

UML类图
在这里插入图片描述

扩展性分析

Tip:很多文章中写的是扩展一个产品族,我不是很理解这种说法,抽象工厂模式整个对应的就只有一个产品族。我觉得应该是汉语理解的问题,只能说扩展产品族,而不能说扩展一个产品族,前者表示我要在一个产品族下新增一个产品等级,后者表示我要新增一个全新的产品族,这就不是扩展了,而是另起炉灶。我是这样理解的,欢迎大家来质疑。

扩展一个产品

需要扩展一个具体产品。同时修改具体工厂层的部分代码。小程度地违背开闭原则。

扩展一个产品等级

需要同时扩展抽象产品层和具体产品层。还要修改最顶层的抽象工厂层来添加额外的创建方法,这会导致所有具体工厂实现都要同步修改,这是非常麻烦的,极大地违背了开闭原则。

优点

  • 将产品的创建和使用分离开来,使得客户端代码更加简洁,并且向客户端隐藏产品的创建细节。
  • 将一系列相关的产品对象的创建工作统一到一个抽象工厂中,客户端只需要访问抽象工厂即可,具体的产品工厂可以灵活替换。
  • 当一个族中的多个对象被设计成一起工作时, 它能够保证客户端始终只使用同一个族中的对象。

缺点

  • 一个产品族下增加新的产品等级非常困难,甚至需要修改抽象层代码和其下所有的实现, 严重违背了“开闭原则”。
  • 增加了代码的复杂性,增加了系统的抽象性,增加了理解难度。

适用场景

  • 系统需要一系列相关或相互依赖的产品对象,并且这些产品对象的实现可能会随着时间的推移而发生变化。
  • 系统需要在运行时动态地选择产品族中的一种,而不是一种单一的产品。
  • 系统需要保证一组产品对象被设计成一起使用,而不是单独使用。
  • 系统需要对一个产品族下不同产品提供统一的访问接口,而不关心产品的具体实现。

二、实现案例

模拟一个产品族,这个产品族包括”形状“和”颜色“两个产品等级,提供相应的创建方法。

1. 代表“形状”的抽象产品层和具体产品层

Tip:注意这里是一个接口,两个实现类,共同定义在一个Shape.java的文件中了。下同。

public interface Shape {
    
    
    void draw();
}

class Square implements Shape{
    
    
    @Override
    public void draw() {
    
    
        System.out.println("我是正方形");
    } 
}

class Circle implements Shape{
    
    
    @Override
    public void draw() {
    
    
        System.out.println("我是圆形");
    }
}

2. 代表“颜色”的抽象产品层和具体产品层

public interface Color {
    
    
    void fill();
}

class Red implements Color{
    
    
    @Override
    public void fill() {
    
    
        System.out.println("我是红色");
    }   
}

class Blue implements Color{
    
    
    @Override
    public void fill() {
    
    
        System.out.println("我是蓝色");
    }  
}

3. 抽象工厂和具体工厂层

//抽象工厂类
public interface AbstractFactory {
    
    
    Shape getShape(String shape);
    Color getColor(String color);
}
//形状工厂类
class ShapeFactory implements AbstractFactory {
    
    
    @Override
    public Shape getShape(String shape){
    
          
       if("square".equalsIgnoreCase(shape)){
    
    
          return new Square();
       } else if("circle".equalsIgnoreCase(shape)){
    
    
          return new Circle();
       }else{
    
    
            return null;
       }
    }
    @Override
    public Color getColor(String color) {
    
    
       return null;
    }
 }
//颜色工厂类
 class ColorFactory implements AbstractFactory {
    
    
    @Override
    public Shape getShape(String shape){
    
          
        return null;
    }
    @Override
    public Color getColor(String color) {
    
    
        if("red".equalsIgnoreCase(color)){
    
    
            return new Red();
         } else if("blue".equalsIgnoreCase(color)){
    
    
            return new Blue();
         }else{
    
    
            return null;
         }
     }
 }

5. 工厂创造器

public class FactoryProducer {
    
    
    //工厂创造器
    public static AbstractFactory createFactory(String choice){
    
    
        if("shape".equalsIgnoreCase(choice)){
    
    
           return new ShapeFactory();
        } else if("color".equalsIgnoreCase(choice)){
    
    
           return new ColorFactory();
        }else{
    
    
            return null;
        }
     }
}

6. 测试类

public class Test {
    
    
    public static void main(String[] args) {
    
    
        //测试形状工厂
        AbstractFactory absFactory01=FactoryProducer.createFactory("shape");
        absFactory01.getShape("circle").draw();

        //测试颜色工厂
        AbstractFactory absFactory02=FactoryProducer.createFactory("color");
        absFactory02.getColor("red").fill();

        //不使用工厂创造器,直接new的形式
        AbstractFactory absFactory03=new ColorFactory();
        absFactory03.getColor("blue").fill();
    }
}

运行结果示例:

image-20230430141636899

三、总结

好了,亲爱的读者朋友们,辛苦大家看到这里,经过本篇博客文章的学习,相信大家已经对抽象工厂模式有了非常深刻的认知。对比工厂方法模式,这个模式确实更加复杂和难以掌握,本文尽量以通俗易懂的形式阐述了抽象工厂模式的设计原理、扩展性及优缺点分析,希望大家结合案例认真理解它的用法,如有疑问欢迎评论斧正。


创作不易,如果本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励,是我创作的最大动力。

猜你喜欢

转载自blog.csdn.net/qq_36756227/article/details/130450108