设计模式-简单工厂模式(帮助理解面向对象)

《大话设计模式》的java翻译版。

在正式介绍工厂模式之前,有一点我想提一下,我觉得《大话设计模式》对面向对象的比喻非常生动,面向过程就比如雕版印刷,而面向对象则是活字印刷术。面向对象有很多优点,比如可维护、可复用、可扩展、灵活性好,而这些都可以在活字印刷术中展现。

当我们使用活字印刷术时:第一,用过一次的字模完全可以使用第二次第三次,此为可复用;第二,如果我们刻错了字,则只需修改该字即可,此为可维护;第三,若需要加入新字,只需另刻字加入即可,此为可扩展;第四,字的顺序方向可以任意排列,横向竖向皆可,此为灵活性好;而这些都是雕版印刷(面向过程)所没有的优点。而这些优点正是因为面向对象所具有的三个基本特征:封装继承多态才能很好的实现,这也是我想分享给大家的。

好了下面进入正文。面试题:用任意一种语言实现一个计算器控制台程序,输入两个数和运算符号,得到结果。

下面为面向过程的代码:

public class Calculator {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入数字A:");
        double a = sc.nextDouble();
        System.out.print("请选择运算符号(+、-、*、/):");
        String symbol = sc.next();
        System.out.print("请输入数字B:");
        double b = sc.nextDouble();
        double result = 0d;
        switch (symbol) {
            case "+":
                result = a - b;
                break;
            case "-":
                result = a - b;
                break;
            case "*":
                result = a * b;
                break;
            case "/":
                result = a / b;
                break;
        }
        System.out.println("A " + symbol + " B = " + result);
    }
}

让我们来分析一下,第一,如果我希望在windows界面或iphone上输入操作,那我必须复制整个方法,并改动其中的一部分代码,才能实现,因为他们的控制台输入部分并不一致,不可复用;第二,显而易见,上面的加法写错了,但是当我想要修改它时,却发现还要编译其余全部的算法,维护风险相当高,而当我们把这一段代码复制到成千上万个平台之后,已经完全不可维护了;第三,当我想要再加入一个开平方的算法,参考第二点,也已经完全不可扩展了。

下面是简单工厂模式的代码:

首先我们抽象(算不算面向对象的特征存在争议)出计算类:

public class Calculator {
    private double num1;
    private double num2;

    double getResult(double num1, double num2, String symbol) {
        return 0;
    }

    public double getNum1() {
        return num1;
    }

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

    public double getNum2() {
        return num2;
    }

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

 然后我们加减乘除类来继承计算类:

class Add extends Calculator {
    @Override
    double getResult() {
        return this.getNum1() + this.getNum2();
    }
}

class Sub extends Calculator {
    @Override
    double getResult() {
        return this.getNum1() + this.getNum2();
    }
}

class Mul extends Calculator {
    @Override
    double getResult() {
        return this.getNum1() * this.getNum2();
    }
}

class Div extends Calculator {
    @Override
    double getResult() throws Exception {
        if (this.getNum2() == 0) {
            throw new Exception("除数不能为0");
        }
        return this.getNum1() + this.getNum2();
    }
}

至此,我们的业务逻辑已经全部实现,与界面逻辑完全分开,我们称此为封装,即我们将业务逻辑封装好了。

当然我们也可以这样写:

public interface ICalculator {
    double getResult(double num1, double num2) throws Exception;
}

class Add implements ICalculator {
    @Override
    public double getResult(double num1, double num2) {
        return num1 + num2;
    }
}

class Sub implements ICalculator {
    @Override
    public double getResult(double num1, double num2) {
        return num1 - num2;
    }
}

class Mul implements ICalculator {
    @Override
    public double getResult(double num1, double num2) {
        return num1 * num2;
    }
}

class Div implements ICalculator {
    @Override
    public double getResult(double num1, double num2) throws Exception {
        if (num2 == 0) {
            throw new Exception("除数不能为0");
        }
        return num1 / num2;
    }
}

工厂类:

public class CalculatorFactory {
    public static ICalculator create(String symbol) {
        ICalculator calculator = null;
        switch (symbol) {
            case "+":
                calculator = new Add();
                break;
            case "-":
                calculator = new Sub();
                break;
            case "*":
                calculator = new Mul();
                break;
            case "/":
                calculator = new Div();
                break;
        }
        return calculator;
    }
}

接口的多种不同的实现方式即为多态。

在简单工厂模式中,我们可以很清晰的体会到面向对象的4个基本特征;

客户端代码:

public class Client {
    public static void main(String[] args) {
        ICalculator calculator1 = CalculatorFactory.create("+");
        ICalculator calculator2 = CalculatorFactory.create("-");
        ICalculator calculator3 = CalculatorFactory.create("*");
        ICalculator calculator4 = CalculatorFactory.create("/");
        try {
            double result1 = calculator1.getResult(6, 2);
            System.out.println(result1);
            double result2 = calculator2.getResult(result1, 2);
            System.out.println(result2);
            double result3 = calculator3.getResult(result2, 2);
            System.out.println(result3);
            double result4 = calculator4.getResult(result3, 2);
            System.out.println(result4);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

那么我们再来分析一下:第一,无论我再任何平台界面操作,我都可以直接使用封装好的业务代码,只需要稍稍修改客户端代码即可,此为可复用;第二,如果我想要修改加法运算,我只需要修改Add类即可,因为所有平台的业务代码都是同一套,所以可维护;第三,如果我想要新增一个开平方的运方法,那我只需要添加一个开平方类实现ICalculator,并修改工程类,同理第二条,可扩展。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值