SpringBoot实践——抽象工厂模式

1,377 阅读3分钟

定义

  • 抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类

  • 简而言之抽象工厂是一个中心超级工厂,创建其他工厂的模式。

优点

  • 单一职责原则,将产品生成代码抽取同一位置,使得代码易于维护。
  • 开闭原则, 在向应用程序中引入新产品变体时, 你无需修改客户端代码。
  • 可以确保同一工厂生成的产品相互匹配。
  • 可以避免客户端和具体产品代码的耦合。

缺点

  • 该模式需要向应用程序中引入众多接口和类, 代码可能会比之前更加复杂。

实践

举例

操作系统分为mac、win,如今需要为各个操作系统设计对应的元素UI,客户端代码无需与具体UI 类耦合,就能创建跨平台的 UI 元素,同时确保所创建的元素与指定的操作系统匹配。

思路

先创建一个操作系统工厂枚举类,再创建操作系统工厂接口,然后创建两个操作系统工厂(假设只有2个:mac、win)类来实现该接口,在这两个类中有创建对应操作系统的UI元素(如按钮、复选框)的方法,最后将两个操作系统工厂类服务存储到map去,按需调取。

代码

  1. 创建操作系统工厂类枚举
/**
 * @Author 勤任风
 * @Description 工厂类枚举
 * @Date  2022/5/21 10:48 
 **/
@Getter
@ToString
public enum FactoryEnum {

    WINDOW("win"),

    MAC("mac");

    private final String name;

    FactoryEnum(String name) {
        this.name = name;
    }
}
  1. 创建GUI工厂接口
/**
 * @Description GUI工厂接口
 * @Date  2022/5/21 11:48 
 * @return
 **/
public interface GUIFactory {

    /**
     * @Description 获取当前工厂的枚举
     **/
    FactoryEnum getFactoryEnum();

    /**
     * @Description 创建按钮
     **/
    Button createButton();

    /**
     * @Description 创建复选框
     **/
    CheckBox createCheckBox();
}
  1. 创建两个工厂:Mac工厂、Win工厂
/**
 * @author 勤任风
 * @date 2022-05-21 10:35
 * @Description Mac工厂
 */
@Component
public class MacFactory implements GUIFactory {
    @Override
    public FactoryEnum getFactoryEnum() {
        return FactoryEnum.MAC;
    }

    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new MacCheckBox();
    }
}
/**
 * @author 勤任风
 * @date 2022-05-21 10:35
 * @Description Win工厂
 */
@Component
public class WinFactory implements GUIFactory {
    @Override
    public FactoryEnum getFactoryEnum() {
        return FactoryEnum.WINDOW;
    }

    @Override
    public Button createButton() {
        return new WinButton();
    }

    @Override
    public CheckBox createCheckBox() {
        return new WinCheckBox();
    }
}
  1. 创建按钮接口、复选框接口
/**
 * @Author 勤任风
 * @Description 按钮接口
 * @Date  2022/5/21 11:50 
 **/
public interface Button {
    void paint();
}
/**
 * @Author 勤任风
 * @Description 复选框接口
 * @Date  2022/5/21 11:50
 **/
public interface CheckBox {
    void paint();
}
  1. 创建复选框、按钮对应系统的样式实现
public class MacButton implements Button {
    @Override
    public void paint() {
        System.out.println("画Mac风格的按钮");
    }
}
public class MacCheckBox implements CheckBox {
    @Override
    public void paint() {
        System.out.println("画Mac风格的复选框");
    }
}
public class WinButton implements Button {
    @Override
    public void paint() {
        System.out.println("画Window风格的按钮");
    }
}
public class WinCheckBox implements CheckBox {
    @Override
    public void paint() {
        System.out.println("画window风格的复选框");
    }
}
  1. 创建工厂类的管理 该类同时实现了InitializingBean, ApplicationContextAware两个接口
/**
 * @author 勤任风
 * @date 2022-05-21 10:43
 * @Description 工厂类的处置,包括初始化、创建
 */
@Service
public class GUIHandlerFactory implements InitializingBean,ApplicationContextAware {


    private ApplicationContext applicationContext;
    // 存储所有工厂类
    private static final Map<String, Supplier<GUIFactory>> FACTORY_MAP = new HashMap<>();

    /**
     * @Description 根据工厂名称创建工厂,从FACTORY_MAP获取
     **/
    public GUIFactory createFactory(String name){
        Supplier<GUIFactory> guiFactorySupplier = FACTORY_MAP.get(name);
        if(guiFactorySupplier!=null){
            return  guiFactorySupplier.get();
        }
        throw  new IllegalArgumentException("没有该工厂");
    }

    @Override
    public void afterPropertiesSet() {
        //将所有实现了GUIFactory的工厂类都初始化到FACTORY_MAP
        applicationContext.getBeansOfType(GUIFactory.class)
                .values()
                .forEach(c -> FACTORY_MAP.put(c.getFactoryEnum().getName(), () -> c));
        System.out.println("初始化完毕");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
  1. 测试类
@RequestMapping("/abstractFactory")
@RestController
public class AbstractFactoryTestController {

    @Autowired
    GUIHandlerFactory guiHandlerFactory;

    @GetMapping("/create")
    public String create(@RequestParam("name")String name){

        GUIFactory factory = guiHandlerFactory.createFactory(name);
        factory.createButton().paint();
        factory.createCheckBox().paint();
        System.out.println("-------------------------------------");
        return "创建工厂成功:"+factory.getFactoryEnum().toString();
    }

}

测试

  • 输入以下地址,调用测试接口,可以看到已经成功加载了Mac工厂类,并且正确调用了对应的方法。 image.png

image.png

  • 测试win: image.png

image.png

扩展

现在实例实现了 mac、win两个工厂,如果要新增一个工厂,可以在枚举类添加一个成员,然后再新建个工厂类实现GUIFactory即可

附上代码目录

image.png

参考

refactoringguru.cn/design-patt… blog.csdn.net/dreamland_z…