目录
- [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 背景
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");
}
}
}