工厂方法属于创建型设计模式。
设计意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
静态工厂使用面向对象的方式,有效的解决了增加新产品给客户端和实现类带来的代码修改问题,封装了创建过程,减低了增加新产品带来的代码修改错误,但是新增功能需要修改客户端代码和工厂创建类的判断逻辑,这样的设计违背了开放-封闭原则,对扩展开放,对修改封闭,那我们就需要找一种方式避免增加新的功能时修改工厂创建方法的逻辑。(毕竟会对原有代码做修改难免会有失误)
工厂方法就是有效解决这个问题的设计模式。
类图:
通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:
- 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品的创建。
- 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就有多少个具体的工厂实现类,每个工厂实现类负责创建一种产品。
- 产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。
- 产品实现。实现产品接口的具体类,不同的产品也需要不同的产品实现类,产品实现类与功能创建类相对应。
通过类图我们还可以看到,每增加一个产品就增加一个对应的工厂来创建它,这样整个工厂和产品体系都没有什么变化,而只是扩展的变化,这就完全符合开放-封闭的原则了。
我来看代码实例:
package com.factory.staticfactory.extend;
/**
* @author gaoxu
* 实践出真知!产品接口
*/
public interface IOperation {
/**计算方法
* @author gaoxu
* @return
*/
public double calculate();
}
产品接口定义产品的处理方式。
package com.factory.staticfactory.extend;
/**
* @author gaoxu
* 实践出真知!抽象父类
*/
public abstract class AbstractOperation implements IOperation{
double numA = 0;
double numB = 0;
public double getNumA() {
return numA;
}
public void setNumA(double numA) {
this.numA = numA;
}
public double getNumB() {
return numB;
}
public void setNumB(double numB) {
this.numB = numB;
}
}
实现接口并提供数据设置公共的方法。
package com.factory.staticfactory.extend;
/**
* @author gaoxu
* 实践出真知!
*/
public class OperationAdd extends AbstractOperation{
@Override
public double calculate() {
return numA+numB;
}
}
package com.factory.staticfactory.extend;
/**
* @author gaoxu
* 实践出真知!
*/
public class OperationSub extends AbstractOperation{
@Override
public double calculate() {
return numA-numB;
}
}
加法、减发类实现各自的业务逻辑。
package com.factory.factorymethod;
import com.factory.staticfactory.extend.IOperation;
/**工厂方法接口
* @author gaoxu
* 实践出真知!
*/
public interface IFactory {
public IOperation createOperation();
}
package com.factory.factorymethod;
import com.factory.staticfactory.extend.IOperation;
import com.factory.staticfactory.extend.OperationAdd;
/**加法工厂类
* @author gaoxu
* 实践出真知!
*/
public class AddFactory implements IFactory{
public IOperation createOperation(){
return new OperationAdd();
}
}
package com.factory.factorymethod;
import com.factory.staticfactory.extend.IOperation;
import com.factory.staticfactory.extend.OperationSub;
/**减发工厂类
* @author gaoxu
* 实践出真知!
*/
public class SubFactory implements IFactory{
public IOperation createOperation(){
return new OperationSub();
}
}
工厂方法的优点:
1:严格遵循面向对象类的设计原则,比如单一职能原则、开-闭原则、依赖倒置原则、迪米特原则。
2:业务实现解耦。
工厂方法是静态工厂的进一步抽象与推广,由于使用了多态性,工厂方法模式保持了静态工厂的优点同时又克服了它的缺点,不过工厂方法自己的缺点是每加一个产品都需要增加一个工厂类,增加了大量的开发工作量。