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

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)具体工厂
  • 代码示例:
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 工厂方法模式

  • 和简单工厂不同的是,不同对象的生产工厂也不同。
  • 代码示例:
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 思考

  • 从这个例子中,看不出工厂方法模式比简单工厂模式好在哪里。
  • 假设需求变化了,需要增加一种类型,那么,对于简单工厂模式,只要修改:
// 新增类
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方法)不需要做任何改动。这反而更好。
  • 对于简单工厂模式,要修改:
// 修改应用层代码
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 改进工厂方法模式

  • 代码示例:
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。

  • 如果新增一种类型:
// 新增类
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这种改进也可以应用到简单工厂模式中。
  • 不过,当创建对象变得复杂时,简单工厂模式就难以应用对了:
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");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值