设计模式(三)工厂方法模式

简单工厂模式虽然使用起来非常简单,但是也存在劣势,特别是在新增产品或对现有产品进行修改时需要对工厂类进行修改,违反了开闭原则。例如:

JAVA程序员进阶(三)简单工厂模式中,我们举了一个形状工厂的例子,当我们需要往工厂中增加产品类型的时候就需要对工厂类进行修改,而且代码中包含大量if else,不够简洁明了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ShapeFactory {

public static Shape getShape(String type){
Shape shape;
if ("circular".equals(type)){
shape = new Circular();
}else if ("triangle".equals(type)){
shape = new Triangle();
}else if ("rectangle".equals(type)){
//新增矩形类型,需要对工厂类进行修改
shape = new Rectangle();
}else{
throw new UnSupportedShapeException();
}
return shape;
}

}

为了克服这个困难,工厂方法模式应运而生。

工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个 类实例化。工厂方法模式让一个类的实例化延迟到其子类。

从定义我们可以看出,工厂方法模式与简单工厂的区别在于:不再使用一个可以创建所有产品的工厂,转而定义一个工厂接口,并为每一个产品创建一个实现该接口的工厂类:

首先定义一个工厂接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package info.aviraer.design_pattern.factory_method;

import info.aviraer.design_pattern.simple_factory.Shape;

/**
* 工厂类接口
* @author Aviraer
*
*/
public interface ShapeIFactory {

public Shape createShape();

}

创建矩形产品:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package info.aviraer.design_pattern.factory_method;

import info.aviraer.design_pattern.simple_factory.Shape;

/**
* 矩形
* @author Aviraer
*
*/
public class Rectangle extends Shape{

@Override
public void draw() {
System.out.println("Rectangle draw.");
}

@Override
public void erase() {
System.out.println("Rectangle erase.");
}

}

创建矩形工厂:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package info.aviraer.design_pattern.factory_method;

import info.aviraer.design_pattern.simple_factory.Shape;

/**
* 矩形工厂
* @author Aviraer
*
*/
public class RectangleFactory implements ShapeIFactory{

public Shape createShape() {
return new Rectangle();
}

}

实现main方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package info.aviraer.design_pattern.factory_method;

import info.aviraer.design_pattern.simple_factory.Shape;

public class App {

public static void main(String[] args) {
//可以通过配置文件决定创建什么类型的工厂
ShapeIFactory factory = new RectangleFactory();
Shape shape = factory.createShape();
shape.draw();
shape.erase();
}

}

 

与简单工厂对比可以看出工厂方法模式的优势在于:

1.继承了简单工厂的所有优势。

2.对产品进行增加时,不需要修改原有代码,符合开闭原则。

 

劣势在于:

1.每一个产品需要一个工厂类,稍显繁琐。

2.引入了工厂接口,增加了理解难度。

 

应用场景:

1.客户端不关心产品的具体类型。

2. 抽象工厂类通过其子类来指定创建哪个对象。