工厂模式
一. 说明
通过一个工厂类来创建对象,而非直接实例化对象,属于创建型模式。
工厂模式分为简单工厂模式和工厂方法模式:
- 简单工厂模式:简单工厂模式定义了一个工厂类,这个工厂类提供一个方法,根据传入的参数不同,返回不同的实例对象。
- 工厂方法模式:工厂方法模式定义了一个抽象的工厂接口,具体的工厂类实现这个接口来创建具体的产品类。
二.应用场景
- 营销活动发奖多种不同类型的商品(实体商品,虚拟商品)
- 项目集成多种数据库,根据数据库类型访问数据库
- 四则运算计算器
- Spring框架中的BeanFactory就是工厂模式的实现
三.代码示例
以四则运算计算器为例,根据这个例子分别实现简单工厂和工厂方法,比较他们的不同点。
1. 简单工厂示例
首先,创建一个抽象产品,表示某个产品类型,在计算器中加减乘除即是运算这一产品的实现
/**
* 运算抽象接口,只有一个获取结果的方法
*/
public interface Operation {
double getResult(double numberA, double numberB);
}
再定义四则运算的实现类,即具体产品
public class Add implements Operation {
@Override
public double getResult(double numberA, double numberB) {
return numberA + numberB;
}
}
public class Sub implements Operation{
@Override
public double getResult(double numberA, double numberB) {
return numberA - numberB;
}
}
public class Mul implements Operation{
@Override
public double getResult(double numberA, double numberB) {
return numberA * numberB;
}
}
public class Div implements Operation {
@Override
public double getResult(double numberA, double numberB) {
if (numberB == 0) {
throw new ArithmeticException();
}
return numberA / numberB;
}
}
最后创建一个工厂类,工厂类负责创建生产具体产品
public class OperationFactory {
public static Operation createOperate(String operate) {
Operation operation = null;
switch (operate) {
case "+":
operation = new Add();
break;
case "-":
operation = new Sub();
break;
case "*":
operation = new Mul();
break;
case "/":
operation = new Div();
break;
}
return operation;
}
}
测试结果输出
public static void main(String[] args) {
Operation add = OperationFactory.createOperate("+");
double result1 = add.getResult(1, 2);
System.out.println("1+2=" + result1);
Operation sub = OperationFactory.createOperate("-");
double result2 = sub.getResult(1, 2);
System.out.println("1-2=" + result2);
Operation mul = OperationFactory.createOperate("*");
double result3 = mul.getResult(1, 2);
System.out.println("1*2=" + result3);
Operation div = OperationFactory.createOperate("/");
double result4 = div.getResult(1, 2);
System.out.println("1/2=" + result4);
}
2. 工厂方法示例
首先,定义四则运算的实现类,即定义产品,同上。
public interface Operation {
double getResult(double numberA, double numberB);
}
public class Add implements Operation {
@Override
public double getResult(double numberA, double numberB) {
return numberA + numberB;
}
}
public class Sub implements Operation{
@Override
public double getResult(double numberA, double numberB) {
return numberA - numberB;
}
}
public class Mul implements Operation{
@Override
public double getResult(double numberA, double numberB) {
return numberA * numberB;
}
}
public class Div implements Operation {
@Override
public double getResult(double numberA, double numberB) {
if (numberB == 0) {
throw new ArithmeticException();
}
return numberA / numberB;
}
}
再定义创建产品的工厂接口和具体工厂类
public interface Factory {
Operation createOperate();
}
public class AddFactory implements Factory{
@Override
public Operation createOperate() {
return new Add();
}
}
public class SubFactory implements Factory{
@Override
public Operation createOperate() {
return new Sub();
}
}
public class MulFactory implements Factory{
@Override
public Operation createOperate() {
return new Mul();
}
}
public class DivFactory implements Factory{
@Override
public Operation createOperate() {
return new Div();
}
}
public class OperationFactory {
public static Operation createOperate(String operate) {
Factory factory = null;
switch (operate) {
case "+":
factory = new AddFactory();
break;
case "-":
factory = new SubFactory();
break;
case "*":
factory = new MulFactory();
break;
case "/":
factory = new DivFactory();
break;
}
return factory.createOperate();
}
}
测试运行
public static void main(String[] args) {
Operation add = OperationFactory.createOperate("+");
double result1 = add.getResult(1, 2);
System.out.println("1+2=" + result1);
Operation sub = OperationFactory.createOperate("-");
double result2 = sub.getResult(1, 2);
System.out.println("1-2=" + result2);
Operation mul = OperationFactory.createOperate("*");
double result3 = mul.getResult(1, 2);
System.out.println("1*2=" + result3);
Operation div = OperationFactory.createOperate("/");
double result4 = div.getResult(1, 2);
System.out.println("1/2=" + result4);
}
四. 疑问
看到这里,你是不是会觉得工厂方法又增加了一套接口和实现,表现得更为复杂了呢?
其实不然,这里目前只存在四则基本运算,如果新增一个指数运算,会怎么样呢?
简单工厂方法的做法是必须在case中新增一个指数运算分支,这就违反了开闭原则。
而工厂方法的做法更优,我们将上述工厂方法的代码进行改造,将四则基本运算和高级运算分为两个不同的工厂类,而不是一个运算使用一个工厂类。
新增一个指数运算
public class Pow implements Operation{
@Override
public double getResult(double numberA, double numberB) {
return Math.pow(numberA, numberB);
}
}
将计算类型分为基本运算和高级运算,创建两个工厂类
public interface IFactory {
Operation createOperate(String operate);
}
//基本运算工厂类
public class BaseFactory implements IFactory{
@Override
public Operation createOperate(String operate) {
Operation operation = null;
switch (operate) {
case "+":
operation = new Add();
break;
case "-":
operation = new Sub();
break;
case "*":
operation = new Mul();
break;
case "/":
operation = new Div();
break;
}
return operation;
}
}
//高级运算工厂类
public class AdvancedFactory implements IFactory {
@Override
public Operation createOperate(String operate) {
Operation operation = null;
switch (operate) {
case "pow":
operation = new Pow();
break;
}
return operation;
}
}
工厂创建类
public class OperationFactory {
public static Operation createOperate(String operate) {
IFactory factory = null;
switch (operate) {
case "+":
case "-":
case "*":
case "/":
factory = new BaseFactory();
break;
case "pow":
factory = new AdvancedFactory();
break;
}
return factory.createOperate(operate);
}
}
此时,我们无论新增多少种高级运算,我们的四则基本运算是无需修改也不受影响的,但这里还是存在不好的地方,新增一种运算,OperationFactory依然需要新增case,这个我们后面去解决它。
五. 总结
工厂模式提供了统一的接口用于创建不同的对象。简单工厂模式在工厂类提供了创建对象的方法,根据传入不同参数创建不同对象;工厂方法模式则是通过创建不同产品的生产工厂类来创建不同产品对象,使类的实例化延迟到了子类。