对简单工厂模式、工厂方法模式的思考

目录

  • [1 背景](#1 背景)
    • [1.1 题目描述](#1.1 题目描述)
    • [1.2 输入描述](#1.2 输入描述)
    • [1.3 输出描述](#1.3 输出描述)
    • [1.4 输入示例](#1.4 输入示例)
    • [1.5 输出示例](#1.5 输出示例)
  • [2 简单工厂模式](#2 简单工厂模式)
  • [3 工厂方法模式](#3 工厂方法模式)
  • [4 思考](#4 思考)
    • [4.1 改进工厂方法模式](#4.1 改进工厂方法模式)

1 背景

题目源自:【设计模式专题之工厂方法模式】2.积木工厂

1.1 题目描述

小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。

1.2 输入描述

输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示生产的次数。

接下来的 N 行,每行输入一个字符串和一个整数,字符串表示积木的类型。积木类型分为 "Circle" 和 "Square" 两种。整数表示该积木生产的数量

1.3 输出描述

对于每个积木,输出一行字符串表示该积木的信息。

1.4 输入示例

3

Circle 1

Square 2

Circle 1

1.5 输出示例

Circle Block

Square Block

Square Block

Circle Block

2 简单工厂模式

  • 一个工厂生产多个对象。
    • (1)抽象对象【通过接口进行抽象】
    • (2)具体对象【通过类实现接口】
    • (3)具体工厂
  • 代码示例:
java 复制代码
public class Main {
    public static void main(String[] args) {
        ShapeFactorySystem shapeFactorySystem = new ShapeFactorySystem(new SimpleShapeFactory());

        Scanner scanner = new Scanner(System.in);
        int count = Integer.parseInt(scanner.nextLine());
        for (int i = 0; i < count; i++) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ");
            String type = parts[0];
            shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));
        }
    }
}

interface Shape {
    void draw(int n);
}

class Circle implements Shape {
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("Circle Block");
        }
    }
}

class Square implements Shape {

    @Override
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("Square Block");
        }
    }
}

class SimpleShapeFactory {
    public Shape createShape(String type) {
        if ("Circle".equals(type)) {
            return new Circle();
        } else if ("Square".equals(type)) {
            return new Square();
        } else {
            throw new RuntimeException("Unknown type");
        }
    }
}

class ShapeFactorySystem {
    private SimpleShapeFactory simpleShapeFactory;

    public ShapeFactorySystem(SimpleShapeFactory simpleShapeFactory) {
        this.simpleShapeFactory = simpleShapeFactory;
    }

    public void produce(String type, int n) {
        Shape shape = simpleShapeFactory.createShape(type);
        shape.draw(n);
    }
}

3 工厂方法模式

  • 和简单工厂不同的是,不同对象的生产工厂也不同。
  • 代码示例:
java 复制代码
public class Main {
    public static void main(String[] args) {
        ShapeFactorySystem shapeFactorySystem = new ShapeFactorySystem(new CircleFactory(), new SquareFactory());

        Scanner scanner = new Scanner(System.in);
        int count = Integer.parseInt(scanner.nextLine());
        for (int i = 0; i < count; i++) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ");
            String type = parts[0];
            shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));
        }
    }
}

interface Shape {
    void draw(int n);
}

class Circle implements Shape {
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("Circle Block");
        }
    }
}

class Square implements Shape {

    @Override
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("Square Block");
        }
    }
}

interface ShapeFactory {
    Shape createShape(String type);
}

class CircleFactory implements ShapeFactory {
    @Override
    public Shape createShape(String type) {
        return new Circle();
    }
}

class SquareFactory implements ShapeFactory {
    @Override
    public Shape createShape(String type) {
        return new Square();
    }
}

class ShapeFactorySystem {
    private ShapeFactory circleFactory;
    private ShapeFactory squareFactory;

    public ShapeFactorySystem(ShapeFactory circleFactory, ShapeFactory squareFactory) {
        this.circleFactory = circleFactory;
        this.squareFactory = squareFactory;
    }

    public void produce(String type, int n) {
        Shape shape;
        if ("Circle".equals(type)) {
            shape = circleFactory.createShape(type);
        } else if ("Square".equals(type)) {
            shape = squareFactory.createShape(type);
        } else {
            throw new RuntimeException("Unknown type");
        }
        shape.draw(n);
    }
}

4 思考

  • 从这个例子中,看不出工厂方法模式比简单工厂模式好在哪里。
  • 假设需求变化了,需要增加一种类型,那么,对于简单工厂模式,只要修改:
java 复制代码
// 新增类
class xxx implements Shape {
    @Override
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("xxx Block");
        }
    }
}

// 修改方法
class SimpleShapeFactory {
    public Shape createShape(String type) {
        if ("Circle".equals(type)) {
            return new Circle();
        } else if ("Square".equals(type)) {
            return new Square();
        } else if (xxx.equals(type)) {
        	...
		} else {
            throw new RuntimeException("Unknown type");
        }
    }
}
  • 但是对应用层代码(main方法)不需要做任何改动。这反而更好。
  • 对于简单工厂模式,要修改:
java 复制代码
// 修改应用层代码
public static void main(String[] args) {
    ShapeFactorySystem shapeFactorySystem = new ShapeFactorySystem(new CircleFactory(), new SquareFactory(), xxx);

    Scanner scanner = new Scanner(System.in);
    int count = Integer.parseInt(scanner.nextLine());
    for (int i = 0; i < count; i++) {
        String line = scanner.nextLine();
        String[] parts = line.split(" ");
        String type = parts[0];
        shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));
    }
}

// 新增类
class xxx implements Shape {
    @Override
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("xxx Block");
        }
    }
}

// 新增类
class xxxFactory implements ShapeFactory {
	...
}

class ShapeFactorySystem {
    private ShapeFactory circleFactory;
    private ShapeFactory squareFactory;
    private xxxFactory ...;

    public ShapeFactorySystem(ShapeFactory circleFactory, ShapeFactory squareFactory, xxxFactory ...) {
        this.circleFactory = circleFactory;
        this.squareFactory = squareFactory;
        ...
    }

    public void produce(String type, int n) {
        Shape shape;
        if ("Circle".equals(type)) {
            shape = circleFactory.createShape(type);
        } else if ("Square".equals(type)) {
            shape = squareFactory.createShape(type);
        } else if (xxx) {
        	...
        } else {
            throw new RuntimeException("Unknown type");
        }
        shape.draw(n);
    }
}
  • 真麻烦啊。

4.1 改进工厂方法模式

  • 代码示例:
java 复制代码
public class Main {
    public static void main(String[] args) {
        ShapeFactorySystem shapeFactorySystem = ShapeFactorySystem.getSingleton();

        Scanner scanner = new Scanner(System.in);
        int count = Integer.parseInt(scanner.nextLine());
        for (int i = 0; i < count; i++) {
            String line = scanner.nextLine();
            String[] parts = line.split(" ");
            String type = parts[0];
            shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));
        }
    }
}

interface Shape {
    void draw(int n);
}

class Circle implements Shape {
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("Circle Block");
        }
    }
}

class Square implements Shape {

    @Override
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("Square Block");
        }
    }
}

interface ShapeFactory {
    Shape createShape();
}

class CircleFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new Circle();
    }
}

class SquareFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new Square();
    }
}

class ShapeFactorySystem {
    private static final Map<ShapeType, ShapeFactory> shapeFactoryMap = new HashMap<>();

    private static ShapeFactorySystem shapeFactorySystem;

    private ShapeFactorySystem() {
        shapeFactoryMap.put(ShapeType.CIRCLE, new CircleFactory());
        shapeFactoryMap.put(ShapeType.SQUARE, new SquareFactory());
    }

    public static ShapeFactorySystem getSingleton() {
        if (shapeFactorySystem == null) {
            synchronized (ShapeFactorySystem.class) {
                if (shapeFactorySystem == null) {
                    shapeFactorySystem = new ShapeFactorySystem();
                }
            }
        }

        return shapeFactorySystem;
    }

    private ShapeFactory acquireShapeFactory(ShapeType type) {
        return shapeFactoryMap.get(type);
    }

    public void produce(String type, int n) {
        ShapeFactory shapeFactory = acquireShapeFactory(ShapeType.of(type));
        Shape shape = shapeFactory.createShape();
        shape.draw(n);
    }
}

enum ShapeType {
    CIRCLE("Circle"), SQUARE("Square");

    private String value;

    private ShapeType(String value) {
        this.value = value;
    }

    private String getValue() {
        return value;
    }

    public static ShapeType of(String value) {
        for (ShapeType shapeType : ShapeType.values()) {
            if (shapeType.getValue().equals(value)) {
                return shapeType;
            }
        }
        // 如果没有找到匹配的枚举对象,可以抛出一个异常或返回null
        throw new IllegalArgumentException("Unknown ShapeType: " + value);
    }
}

多线程场景下,不能用HashMap。

  • 如果新增一种类型:
java 复制代码
// 新增类
class xxx implements Shape {

    @Override
    public void draw(int n) {
        for (int i = 0; i < n; i++) {
            System.out.println("xxx Block");
        }
    }
}

// 新增类
class xxxFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new xxx();
    }
}

// 修改方法(不修改之前代码,新增语句)
private ShapeFactorySystem() {
   shapeFactoryMap.put(ShapeType.CIRCLE, new CircleFactory());
   shapeFactoryMap.put(ShapeType.SQUARE, new SquareFactory());
}

// 不修改之前的代码,加一个枚举对象
enum ShapeType {
    CIRCLE("Circle"), SQUARE("Square"), xxx;
    ...
}
  • 当然了,通过map + enum这种改进也可以应用到简单工厂模式中。
  • 不过,当创建对象变得复杂时,简单工厂模式就难以应用对了:
java 复制代码
class SimpleShapeFactory {
    public Shape createShape(String type) {
        if ("Circle".equals(type)) {
            return new Circle(); // 简单对象
        } else if ("Square".equals(type)) {
            return new Square(); // 简单对象
        } else {
            throw new RuntimeException("Unknown type");
        }
    }
}
相关推荐
num_killer6 小时前
小白的Langchain学习
java·python·学习·langchain
期待のcode7 小时前
Java虚拟机的运行模式
java·开发语言·jvm
程序员老徐7 小时前
Tomcat源码分析三(Tomcat请求源码分析)
java·tomcat
a程序小傲7 小时前
京东Java面试被问:动态规划的状态压缩和优化技巧
java·开发语言·mysql·算法·adb·postgresql·深度优先
仙俊红7 小时前
spring的IoC(控制反转)面试题
java·后端·spring
阿湯哥7 小时前
AgentScope Java 集成 Spring AI Alibaba Workflow 完整指南
java·人工智能·spring
小楼v7 小时前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法
与遨游于天地7 小时前
NIO的三个组件解决三个问题
java·后端·nio
czlczl200209258 小时前
Guava Cache 原理与实战
java·后端·spring
yangminlei8 小时前
Spring 事务探秘:核心机制与应用场景解析
java·spring boot