工厂方法模式

这一生的挚爱 提交于 2020-01-14 18:54:12

工厂方法模式

1.定义

  • 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

2.为什么使用工厂方法模式

  • 基于简单工厂模式,如果新增了产品类,同时就要在工厂类中新增逻辑判断,修改原有的类。这样就违背了开放-封闭原则。-------见设计模式
  • 如果产品类越来越多,那么就会造成工厂类的臃肿。正是因为工厂类的设计违背了“开放--封闭”原则,所以才会导致新需求到来后修改导致的臃肿。
  • 既然是这个工厂类与分支耦合,那么我们就对它下手,根据依赖倒转原则我们就把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有要生产具体类的工厂,就去实现这个接口。这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂。我们需要新增功能时,就不用修改原有的工厂类了,只需要增加此功能的类和相应的工厂类就可以了。

  • 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现产品类,选择判断的问题还是会存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你想要加功能,本来是改工厂的,而现在是修改客户端。
  • 总结:
    • 1.工厂方法模式其实就是:针对简单工厂模式违背“开放--封闭”原则的地方,依据依赖倒转原则,对工厂类抽象出接口。
    • 2.简单工厂模式最大的优点其实是对于客户端来说,去除了与具体产品的依赖(即解耦)。也就是说,当年之所以总结出简单工厂模式就是为了不让客户端与具体产品类耦合过深。
      • 所谓设计模式,就是前人依据踩过的无数坑总结出的一些规避的惯用写法。
        • 所以使用简单工厂模式与不使用该模式最明显的区别应该就是客户端与具体的产品类耦合。
    • 3.代码的改动是不可避免的,但是改动要合理。工厂方法模式下修改代码是符合“单一职责原则”与“开放--封闭”原则的。

3.如何实现

  • 工厂方法模式实例:同简单工厂,以计算器应用为例
public class Operation {

    private double numberA;

    private double numberB;

    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;
    }

    public double getResult() {
        double result = 0d;
        return result;
    }
}

package cn.sun.code.eight.ifactory;

import cn.sun.code.one.ouhe.Operation;

class OperationAdd extends Operation {

    public double getResult() {
        double result = 0d;
        result = this.getNumberA() + this.getNumberB();
        return result;
    }

}

package cn.sun.code.eight.ifactory;

import cn.sun.code.one.ouhe.Operation;

class OperationSub extends Operation {

    public double getResult() {
        double result = 0d;
        result = this.getNumberA() - this.getNumberB();
        return result;
    }

}

package cn.sun.code.eight.ifactory;

import cn.sun.code.one.ouhe.Operation;

class OperationMul extends Operation {

    public double getResult() {
        double result = 0d;
        result = this.getNumberA() * this.getNumberB();
        return result;
    }

}

package cn.sun.code.eight.ifactory;

import cn.sun.code.one.ouhe.Operation;

class OperationDiv extends Operation {

    public double getResult() {
        double result = 0d;
        if(getNumberB()==0)
            throw new RuntimeException("除数不能为0");
        result = this.getNumberA() / this.getNumberB();
        return result;
    }

}

package cn.sun.code.eight.ifactory;

import cn.sun.code.one.ouhe.Operation;

/**
 * 工厂接口
 */
public interface IFactory {

    Operation createOperation();

}

package cn.sun.code.eight.ifactory;

import cn.sun.code.one.ouhe.Operation;

/**
 * 具体工厂类
 */
public class AddFactory implements IFactory {
    
    @Override
    public Operation createOperation() {
        return new OperationAdd();
    }
    
}

class SubFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationSub();
    }

}

class MulFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationMul();
    }

}

class DivFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationDiv();
    }

}

/**
 * 客户端
 */
class Client{
    
    public static void main(String[] args) {
        IFactory operFactory = new AddFactory();
        Operation operation = operFactory.createOperation();
        operation.setNumberA(1D);
        operation.setNumberB(2D);
        double result = operation.getResult();
        System.out.println(result);
    }
    
}

4.工厂模式在Java中的应用

  • 适用场景
    • 创建对象需要大量重复的代码。
    • 客户端不依赖于产品实例如何被创建、实现等细节。
  • 优点
    • 用户只需关心所需产品对应的工厂,无须关心创建细节。
    • 加入新产品符合开闭原则,提高了系统的可扩展性。
  • 缺点
    • 类个数容易过多,增加了代码结构的复杂性。
    • 增加了系统的抽象性和理解难度。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!