设计模式:工厂方法模式
简单工厂模式
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
接下来我们以设计一个计算器为例子:
该模式中包含的角色及其职责:
-
工厂(Creator)角色(OperationFactory类)
简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。 -
抽象产品(Product)角色(Operation类)
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。 -
具体产品(Concrete Product)角色(OperationAdd类、OperationSub等类)
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
其UML图如下:
JAVA源代码:
package SimpleFactory;
import static Tools.Print.*; //实现println方法、使得输出更方便
abstract class Operation {
public double numberA;
public double numberB;
public abstract double getResult();
}
class OperationAdd extends Operation {
@Override
public double getResult() {
return numberA + numberB;
}
}
class OperationSub extends Operation {
@Override
public double getResult() {
return numberA - numberB;
}
}
class OperationMul extends Operation {
@Override
public double getResult() {
return numberA * numberB;
}
}
class OperationDiv extends Operation {
@Override
public double getResult() {
return (numberB == 0 ? 0 : (numberA / numberB));
}
}
class OperationFactory {
public static Operation createOperation(String operator) {
switch (operator) {
case "+":
return new OperationAdd();
case "-":
return new OperationSub();
case "*":
return new OperationMul();
case "/":
return new OperationDiv();
default:
return null;
}
}
}
//Test SimpleFactory Pattern
public class PatternTest {
public static void main(String[] args) {
Operation oper = OperationFactory.createOperation("*");
oper.numberA = 255;
oper.numberB = 48;
println(oper.getResult());
}
}
简单工厂模式优缺点
- 优点:
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。 - 缺点:
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;如果需要添加新的类,则就需要改变工厂类了,对系统的维护和扩展非常不利;
这些缺点在工厂方法模式中得到了一定的克服。
工厂方法模式
工厂方法模式(factory method)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是:
抽象工厂、具体工厂、抽象产品、具体产品。
接下来我们还以一个计算器为例子:
- 抽象工厂(Creator)角色(OperationFactory类):
工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。 - 具体工厂(Concrete Creator)角色(AddFactory、SubFactory等类):
这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。 - 抽象产品(Product)角色(Operation类):
工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是Light。 - 具体产品(Concrete Product)角色(OperationAdd、OperationSub等类):
这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
其UML图如下:
JAVA源代码:
import static Tools.Print.*;
abstract class Operation {
public double numberA;
public double numberB;
public abstract double getResult();
}
interface OperationFactory {
Operation createOperation();
}
class OperationAdd extends Operation {
@Override
public double getResult() {
return numberA + numberB;
}
}
class OperationSub extends Operation {
@Override
public double getResult() {
return numberA - numberB;
}
}
class OperationMul extends Operation {
@Override
public double getResult() {
return numberA * numberB;
}
}
class OperationDiv extends Operation {
@Override
public double getResult() {
return (numberB == 0 ? 0 : (numberA / numberB));
}
}
class AddFactory implements OperationFactory {
@Override
public Operation createOperation() {
return new OperationAdd();
}
}
class SubFactory implements OperationFactory {
@Override
public Operation createOperation() {
return new OperationSub();
}
}
class MulFactory implements OperationFactory {
@Override
public Operation createOperation() {
return new OperationMul();
}
}
class DivFactory implements OperationFactory {
@Override
public Operation createOperation() {
return new OperationDiv();
}
}
//Test FactoryMethod Pattern
public class PatternTest {
public static void main(String[] args) {
OperationFactory operFac = new AddFactory();
Operation oper = operFac.createOperation();
oper.numberA = 488;
oper.numberB = 968;
println(oper.getResult());
}
}
工厂方法模式 vs. 简单工厂模式
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对客户端来说,去除了与具体产品的依赖。
在简单工厂模式中,你只需要把运算符号,例如“+”传给工厂类即可获得相应的实例,但是如果我们想加入一个其他的运算符号,不光需要实现运算符的实例,而且还要在工厂类的switch条件语句中,加入新的case判断,因为我们修改了原有类,这就完全违背了开放-封闭的原则。
简单工厂模式只存在工厂类负责创建的对象比较少;客户只知道传入工厂类的参数,对于如何创建对象不关心,一般只在很简单的情况下应用。
- 工厂方法模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,更符合开-闭原则:新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可;更符合单一职责原则 ,每个具体工厂类只负责创建对应的产品;而不像简单工厂模式的工厂类使用静态工厂方法,更容易实现多态结构。