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

目录

  • [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");
        }
    }
}
相关推荐
醒了就刷牙25 分钟前
黑马Java面试教程_P9_MySQL
java·mysql·面试
m0_7482336431 分钟前
SQL数组常用函数记录(Map篇)
java·数据库·sql
编程爱好者熊浪1 小时前
JAVA HTTP压缩数据
java
吴冰_hogan2 小时前
JVM(Java虚拟机)的组成部分详解
java·开发语言·jvm
白宇横流学长3 小时前
基于java出租车计价器设计与实现【源码+文档+部署讲解】
java·开发语言
数据小爬虫@4 小时前
Java爬虫实战:深度解析Lazada商品详情
java·开发语言
咕德猫宁丶5 小时前
探秘Xss:原理、类型与防范全解析
java·网络·xss
F-2H6 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
苹果酱05676 小时前
「Mysql优化大师一」mysql服务性能剖析工具
java·vue.js·spring boot·mysql·课程设计
_oP_i7 小时前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源