设计模式笔记 工厂方法模式

  再简单工厂模式中,如果要添加新的产品,为了配合使用就必须修改工厂类,无疑这就破坏了”开放-闭合“原则。但是这也是简单工厂的优点,简单工厂类包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,取出来客户端对具体产品的依赖。为了解耦合和符合”开放-闭合“原则,工厂模式来了。

  定义:定义一个用于创建对象的工厂接口,让子类决定实例化哪一个类。核心工厂类成为一个抽象工厂角色,负责工厂子类必须实现的接口,达到添加新的产品时不必修改核心工厂类,而是添加工厂子类。

  UML类图如下

  继续沿用上篇简单工厂中的例子,实现如下。

  首先是产品类,这里是运算符类,两个操作数参数和一个运算方法,此处用的是抽象类:

public abstract 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 abstract double getResult();
}

   具体产品衍生类,便是各个运算符的运算(加减乘除等),需要继承或实现产品类:

public class OperationAdd extends Operation {

    @Override
    public double getResult() {
        return getNumberA() + getNumberB();
    }
}
public class OperationSub extends Operation {

    @Override
    public double getResult() {
        return getNumberA() - getNumberB();
    }
}
public class OperationMul extends Operation {

    @Override
    public double getResult() {
        return getNumberA() * getNumberB();
    }
}
public class OperationDiv extends Operation {

    @Override
    public double getResult() {
        return getNumberA() / getNumberB();
    }
}

  其次是核心工厂类,是一个接口

public interface IFactory {
    public Operation createOperation();
}

   具体实现工厂的子类,便是各个运算符的运算(加减乘除等),需要实现核心工厂类:

public class AddFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new OperationAdd();
    }
}
public class SubFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new OperationSub();
    }
}
public class MulFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new OperationMul();
    }
}
public class DivFactory implements IFactory {
    @Override
    public Operation createOperation() {
        return new OperationDiv();
    }
}

   最后是客户端,调用

public class POC {
    public static void main(String[] args) {
        coal();
    }

    public static void coal() {
        try {
            double numberA, numberB;
            String opr;
            @SuppressWarnings("resource")
            Scanner sc = new Scanner(System.in);
            System.out.print("输入第一个数字:");
            String numberAStr = sc.next();

            numberA = Double.parseDouble(numberAStr);
            System.out.print("输入操作符:");
            opr = sc.next();

            System.out.print("输入第二个数字:");
            String numberBStr = sc.next();
            numberB = Double.parseDouble(numberBStr);

            IFactory factory = null;
            switch (opr) {
            case "+":
                factory = new AddFactory();
                break;
            case "-":
                factory = new SubFactory();
                break;
            case "*":
                factory = new MulFactory();
                break;
            case "/":
                factory = new DivFactory();
                break;

            default:
                factory = new AddFactory();
                break;
            }
            Operation operation = factory.createOperation();
            operation.setNumberA(numberA);
            operation.setNumberB(numberB);
            System.out.println(numberAStr + opr + numberBStr + "=" + operation.getResult());
        } catch (Exception e) {
            System.out.println("输入有误,请重新开始。。。");
            coal();
        }
    }
}

 

  可以看出添加产品时没有修改的变化,只有扩展的变化。但是,实例化工厂时选择判断的问题还是存在的,只是从工厂类移动到了客户端。但是,工厂方法模式既克服了简单工厂违背的设计原则,也保持了封装对象创建过程的优点,更换对象时不需要大范围的更改,降低了客户端与产品对象的耦合度。

  工厂方法模式是简单工厂的进一步抽象和推广,利用了多态性保证了简单工厂的优点克服了缺点。但是没有避免修改客户端代码的诟病还是存在,所以可以利用反射解决分支问题,关于这点,以后再谈。

原文地址:https://www.cnblogs.com/adamJin/p/7063451.html