Simple Factory Pattern
1. 什么是简单工厂模式
简单工厂模式(Simple Factory Pattern): 定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。简单工厂模式提供一个静态(static)方法来创建对象实例。
简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
2. 简单工厂模式创建流程
- 将需要创建的各种不同对象的相关代码封装到不同的类中,这些类称为具体产品类。
- 将具体产品类的公共代码进行抽象和提取后封装在一个抽象产品类中,如果很复杂的话,抽象出一个层次结构,每一个具体产品类都是抽象产品类的子类。
- 然后提供一个工厂类用于创建各种产品,在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入的参数不同创建不同的具体产品对象;
- 客户端只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。
要点:只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
3. 简单工厂模式类角色解析
简单工厂模式结构图:
-
Factory(工厂类):
工厂类是简单工厂模式的核心,负责创建所有产品实例;
工厂类可以被外界直接调用,创建所需的产品对象;
工厂类中提供了静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product(多态)。 -
Product(抽象产品类):
Product类是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法。
它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,返回该抽象父类即可。 -
ConcreteProduct(具体产品角色):
ConcreteProduct类是简单工厂模式的创建目标,即实例对象,是抽象产品类Product的具体实现。
4. 简单工厂模式优缺点
优点:
- 它包含了必要的判断逻辑,客户端可以免除直接创建产品对象的职责,而仅仅消费对象。简单工厂模式实现了对象创建和使用的分离。
- 客户端只需使用所列参数便可得到对应的对象实例,提高代码阅读性。
缺点:
- 扩展困难,一旦添加新产品就要修改工厂逻辑
- 处于对产品进行实例化的中心位置,它需要知道每一个产品对象的创建细节,如果每个对象实例化需要很多参数、步骤,将会造成在工厂类中堆积大量的代码。而此时如果再添加一个类型的产品实例,将会变得十分复杂。
- 具体产品与工厂类之间的耦合度高,降低了系统的灵活性和扩展性
5. 代码示例
/*
抽象父类
*/
public abstract class Paint {
public abstract void draw();
public abstract void erase();
public static final int PAINT_CIRCLE = 1;
public static final int PAINT_RECT = 2;
public static final int PAINT_TRIANGLE = 3;
/*
静态工厂方法
*/
public static Paint getPaint(int paint) {
Paint mPaint;
switch (paint) {
case PAINT_CIRCLE:
mPaint = new CirclePaint();
break;
case PAINT_RECT:
mPaint = new RectanglePaint();
break;
case PAINT_TRIANGLE:
mPaint = new TrianglePaint();
break;
default:
throw new UnSupportedShapeException();
}
return mPaint;
}
}
/*
具体实现类
*/
public class RectanglePaint extends Paint {
@Override public void draw() {
System.out.println("画方形");
}
@Override public void erase() {
System.out.println("擦除圆");
}
}
/*
具体实现类
*/
public class CirclePaint extends Paint {
@Override public void draw() {
System.out.println("画圆");
}
@Override public void erase() {
System.out.println("擦除圆");
}
}
/*
测试类
*/
public class MainClass {
public static void main(String[] args) {
Paint paint = Paint.getPaint(Paint.PAINT_CIRCLE);
paint.draw();
paint.erase();
}
}