简单工厂模式

前言:这两天学习了简单工厂模式、工厂方法模式、抽象工厂模式,在这里详细说一下简单工厂模式。转载请注明出处:https://www.cnblogs.com/yuxiaole/p/9280695.html

简单工厂模式

定义:简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。  

使用的设计原则:对修改关闭,对扩展开放。

优点:简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

缺点:在简单工厂模式中,工厂类与分支耦合,也就是说如果要新加一个(在工厂类中加一个分支)类,需要在工厂类里去加“Case”分支条件的,就会导致修改原有的类,违背了开放-封闭原则。

举例说明:

  要求:使用面向对象实现一个计算器控制台程序,要求输入两个数字和运算符号,得到结果。

  重点:使用面向对象思想。

  使用简单工厂实现

类图:

 

运算抽象类

/**
 * 运算抽象类
 */
abstract class Operation{
    private int num1;
    private int num2;

    public int getNum1() {
        return num1;
    }

    public void setNum1(int num1) {
        this.num1 = num1;
    }

    public int getNum2() {
        return num2;
    }

    public void setNum2(int num2) {
        this.num2 = num2;
    }

    public abstract double getResult();
}

运算具体类

/**
 * 加法运算
 */
class AddOperation extends Operation{
    @Override
    public double getResult() {
        return getNum1() + getNum2();
    }
}

/**
 * 减法运算
 */
class SubOperation extends Operation{
    @Override
    public double getResult() {
        return getNum1() - getNum2();
    }
}

/**
 * 除法运算
 */
class DivOperation extends Operation{
    @Override
    public double getResult() {
        return getNum1() / getNum2();
    }
}

/**
 * 乘法运算
 */
class MulOperation extends Operation{
    @Override
    public double getResult() {
        return getNum1() * getNum2();
    }
}

运算简单工厂

所有在用简单工厂方法的地方,都可以考虑用反射的技术来去除 switch 或 if ,解除分支判断带来的耦合。

/**
 * 运算简单工厂
 */
class OperationFactory{
    public static Operation createOperation(String type){
        Operation operation;
        switch (type){
            case "+":
                operation = new AddOperation();
                break;
            case "-":
                operation = new SubOperation();
                break;
            case "*":
                operation = new MulOperation();
                break;
            case "/":
                operation = new DivOperation();
                break;
            default:
                operation = null;
        }
        return operation;
    }
}

客户

public static void main(String[] args) throws IOException {

        try{
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入第一位数字:");
            int num1 = scanner.nextInt();
            System.out.println("请输入操作符:");
            String flag = scanner.next();
            System.out.println("请输入第二位数字:");
            int num2 = scanner.nextInt();

            Operation operation = OperationFactory.createOperation(flag);
            operation.setNum1(num1);
            operation.setNum2(num2);
            System.out.println(operation.getResult());

        }catch (Exception e){
            e.printStackTrace();
            System.out.println("您输入有误!");
        }
    }

使用普通方式实现:

上面的例子如果不适用简单工厂则是下面这样,虽然使用了面向对象的封装,但以后一旦涉及到有开放等运算需要加进来时就不满足对修改关闭,对扩展开放的设计原则了:

class Operation{
    public static double getResult(int num1, int num2, String operationFlag){
        if(operationFlag.equals("+")){
            return num1 + num2;
        }else if(operationFlag.equals("-")){
            return num1 - num2;
        }else if(operationFlag.equals("*")){
            return num1 * num2;
        }else if(operationFlag.equals("/")){
            return num1 / num2;
        }
        return 0;
    }
}
public static void main(String[] args) throws IOException {

        try{
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入第一位数字:");
            int num1 = scanner.nextInt();
            System.out.println("请输入操作符:");
            String flag = scanner.next();
            System.out.println("请输入第二位数字:");
            int num2 = scanner.nextInt();

            System.out.println(Operation.getResult(num1, num2, flag));

        }catch (Exception e){
            e.printStackTrace();
            System.out.println("您输入有误!");
        }
    }

 

总结:

  1、new 是在实例化一个具体类,有时需要在运行时才知道需要实例化哪一个类(如下),但是这样的代码一旦有变化和扩展(以后某一天可能会不适用具体类1,而使用一个具体类4;或者增加一个 else if)时,就必须重新考虑这段代码是否符合现有需求。所以才会想到“将变化的东西从不变的地方抽离出来”,这里不变的是方法的调用,变化的是实例化哪一个具体类。最后将变化的地方抽出来单独放在另一个对象(只管如何创建具体类)里面去,这个单独的对象为“工厂”,即工厂只做对象的创建,不管其他的。

        接口 test = null;
        if(....){
            test = new 具体类1();
        }else if(...){
            test = new 具体类2();
        }else{
            test = new 具体类3();
        }
     test.方法1();//每个具体类都有的方法
     test.方法2();//每个具体类都有的方法

     //使用test 做其他的操作.....

  2、简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。

  3、不要因为简单工厂不是一个“真正的”设计模式,就忽略了它的用法。

 

其他工厂模式https://www.cnblogs.com/yuxiaole/p/9276396.html

 

转载请注明出处:https://www.cnblogs.com/yuxiaole/p/9280695.html

 

参考书籍:《Head First 设计模式》《大话设计模式》

posted @ 2018-07-08 17:33  取个名字吧  阅读(216)  评论(0编辑  收藏  举报