工厂方法模式(Factory Pattern)是创建型设计模式之一。
一、定义
简单工厂模式又称为静态方法工厂模式,是由一个工厂对象决定创建哪一种产品类的实例。(一个工厂方法创建不同类型的对象)
二、适用场景
- 工厂类负责创建的对象比较少
- 客户端(应用层)只知道传入工厂类的参数对于如何创建对象(逻辑不关心)
三、优点
- 只需要传入一个正确的参数,就可以获取你所需要的对象而无需知道其创建细节
四、缺点
- 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则
- 简单工厂模式使用了静态工厂方法,因此静态方法不能被继承和重写
- 工厂类包含了所有实例(产品)的创建逻辑,若工厂类出错,则会造成整个系统都会会受到影响
五、实现
创建一个可以绘制不同形状的绘图工具,可以绘制圆形,正方形,三角形,每个图形都会有一个 draw() 方法用于绘图
正方形,三角形都属于一种图形,并且都具有draw方法,所以首先可以定义一个接口或者抽象类,作为这三个图像的公共父类,并在其中声明一个公共的draw方法。
public interface Shape {
void draw();
}
这里定义为抽象类也可以,只不过接口是更高一级的抽象类,所以习惯定义成接口,而且接口支持多实现,方便以后扩展。
下面就是编写具体的图形,每种图形都实现 Shape 接口
/**
* 圆形
*/
public class CircleShape implements Shape {
public CircleShape() {
System.out.println("CircleShape: created");
}
@Override
public void draw() {
System.out.println("draw: CircleShape");
}
}
/**
* 正方形
*/
public class RectShape implements Shape {
public RectShape() {
System.out.println("RectShape: created");
}
@Override
public void draw() {
System.out.println("draw: RectShape");
}
}
/**
* 三角形
*/
public class TriangleShape implements Shape {
public TriangleShape() {
System.out.println("TriangleShape: created");
}
@Override
public void draw() {
System.out.println("draw: TriangleShape");
}
}
下面是工厂类的具体实现:
public class ShapeFactory {
/**
* 根据 type 类型判断返回的子类实现
*
* @param type type
* @return Shape
*/
public static Shape getShape(String type) {
Shape shape = null;
if (type.equalsIgnoreCase("circle")) {
shape = new CircleShape();
} else if (type.equalsIgnoreCase("rect")) {
shape = new RectShape();
} else if (type.equalsIgnoreCase("triangle")) {
shape = new TriangleShape();
}
return shape;
}
}
在这个工厂类中通过传入不同的 type 可以 new 不同的形状,返回结果为 Shape 类型,这个就是简单工厂核心的地方了。
客户端使用:
//画圆形
Shape shape= ShapeFactory.getShape("circle");
shape.draw();
//画正方形
Shape shape= ShapeFactory.getShape("rect");
shape.draw();
//画三角形
Shape shape= ShapeFactory.getShape("triangle");
shape.draw();
只通过给 ShapeFactory 传入不同的参数就实现了各种形状的绘制。以上就是简单工厂方式。但是不符合开闭原则
使上面代码示例易扩展并支持开闭原则
,可把工厂类改为如下:
public class ShapeFactory {
public static Shape getShape(Class c) {
Shape shape = null;
try {
shape = (Shape) Class.forName(c.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return shape;
}
}
客户端使用:
Shape shape = ShapeFactory.getShape(RectShape.class);
shape.draw();
只通过给 ShapeFactory 传入不同的 class 就实现了各种形状的绘制,即使有新的扩展,也不需要修改工厂类。符合开闭原则的定义:对于扩展是开放的,对于修改是封闭的。