一、工厂方法模式定义
定义:一个创建产品对象的工厂接口,让子类决定实例化哪一种实例对象,也就是将实际创建实例对象的工作推迟到子类当中,核心工厂类不再负责具体产品的创建。
工厂方法模式是对简单工厂模式进行了抽象。如此一来核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。工厂方法模式完全实现“开-闭”原则,对扩展开放,对修改关闭。
二、工厂方法模式的作用
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一类。
三、工厂方法使用
3.1 当一个类不知道它所需要的对象的类时
在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道说对应的工厂即可;
3.2 当一个类希望通过其子类来指定创建对象时
在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
3.3 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
四、工厂方法模式图
4.1模式组成
组成(角色) | 关系 | 作用 |
抽象产品(Product) | 具体产品的父类 | 描述具体产品的公共接口 |
具体产品(ConcreteProduct) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
抽象工厂(Creator) | 具体工厂的父类 | 描述具体工厂的公共接口 |
具体工厂(ConcreteCreator) | 抽象工厂的子类;被外界调用 | 描述具体工厂;实现actoryMethod工厂方法创建产品的实例 |
五、工厂方法模式的典型
5.1抽象产品
public abstract class Product {
private String productName;
public Product(){
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}
5.2 具体产品
public class ProductA extends Product {
public ProductA(){
this.setProductName("productA");
}
}
public class ProductB extends Product {
public ProductB(){
this.setProductName("productB");
}
}
5.3 抽象工厂
public interface Factory {
public Product createProduct();
}
5.4 具体工厂
public class FactoryA implements Factory{
@Override
public Product createProduct() {
// TODO Auto-generated method stub
return new ProductA();
}
}
public class FactoryB implements Factory{
@Override
public Product createProduct() {
// TODO Auto-generated method stub
return new ProductB();
}
}
5.5 产品的使用
public class Realization {
public static void main(String[] args) {
Factory factory = new FactoryA();
Product product = factory.createProduct();
System.out.println(product.getProductName());
}
}
六、工厂方法模式实例——运算
6.1 运算
public class Operation {
private double numberA;
private double numberB;
public double getResult() {
double result = 0.0;
return result;
}
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
}
6.2加法运算
public class AddOperation extends Operation {
@Override
public double getResult() {
// TODO Auto-generated method stub
return this.getNumberA()+this.getNumberB();
}
}
6.3 工厂
public interface OperationFactory {
public Operation getResult();
}
6.4 加法对应的工厂
public class AddOperationFact implements OperationFactory{
@Override
public Operation getResult() {
// TODO Auto-generated method stub
return new AddOperation();
}
}
6.5 实现
public class Realization {
public static void main(String[] args) {
OperationFactory factory = new AddOperationFact();
Operation operation = factory.getResult();
operation.setNumberA(3);
operation.setNumberB(5);
System.out.println(operation.getResult());
}
}
七、工厂方法模式的优缺点
7.1优点
1》更符合开-闭原则
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
2》符合单一职责原则
每个具体工厂类只负责创建对应的产品
3》不使用静态工厂方法,可以形成基于继承的等级结构
总结:工厂模式可以说是简单工厂模式的进一步抽象和扩展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
7.2 缺点
1》添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统地复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
2》由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统地抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统地实现难度;
3》虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
4》一个具体工厂只能创建一种具体产品