第1章 代码无错便是优?——简单工厂模式

1.1 面试受挫

要求:面向对象编程语言写一个计算器小程序!

下面例子是面向过程编程实现,而且有一些小问题

package com.designPattern.v1;

import java.util.Scanner;
/**
 * 
 */
public class Cacultor01 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        double a = 0,b = 0,c = 0;
        String op = null;
        //输入的类型与想要的不符怎么办?
        System.out.println("请输入数字A:");
        if(scan.hasNextDouble()) {
            a = scan.nextDouble();
        } else {
            System.out.println("非数字,请重新输入");
        }
        
        System.out.println("请输入符号:+ - * /");
        if(scan.hasNext()) {
            op = scan.next();
        }
            
        System.out.println("请输入数字B:");
        if(scan.hasNextDouble()) {
            b = scan.nextDouble();
        }
        //else
        if(op == "+")
            c = a + b;
        if(op == "-")
            c = a - b;
        if(op == "*")
            c = a * b;
        if(op == "/")
            c = a / b; //输入了0怎么办?
        System.out.println(a + " " + op + b + " = " + c);
        scan.close();
    }
}

1.2 初学者代码的毛病

  1. 命名规范
  2. if判断
  3. 异常校验

1.3 代码规范

改进版本:规范了变量命名,分支优化,加了异常捕获

package com.designPattern.v1;

import java.util.Scanner;

public class Cacultor02 {
    public static void main(String[] args) {
        try {
            Scanner scan = new Scanner(System.in);
            double number1 = 0,nubmer2 = 0;
            String op = null,result = null;
            //输入的类型与想要的不符怎么办?
            System.out.println("请输入数字A:");
            if(scan.hasNextDouble()) {
                number1 = scan.nextDouble();
            } else {
                throw new Exception("数字类型规范");
            }
            
            System.out.println("请输入符号:+ - * /");
            if(scan.hasNext()) {
                op = scan.next();
            }
                
            System.out.println("请输入数字B:");
            if(scan.hasNextDouble()) {
                nubmer2 = scan.nextDouble();
            } else {
                throw new Exception("数字类型规范");
            }
            switch(op) {
                case "+" : result = number1 + nubmer2 + "";break;
                case "-" : result = number1 - nubmer2 + "";break;
                case "*" : result = number1 * nubmer2 + "";break;
                case "/" : 
                    if(nubmer2 != 0)
                        result = (number1 / nubmer2) + "";
                    else
                        result = "除数不能为0";
                    break;
                default : result = "请按提示输入操作符!";break;
            }
            System.out.println("结果是 "+ result);
            scan.close();
        } catch(Exception e) {
            e.printStackTrace();
            System.out.println("您输入的参数不符合规范");
            System.exit(-1);
        }
    }
}

1.4 面向对象编程

上面是面向过程的计算机处理问题的逻辑,这本身并没有什么错。
只是这使得程序只为满足当前程序需求,程序不容易 维护、扩展、复用。非高质量也!

1.5 活体印刷,面向对象

第一、要改,只需更改要改之字,此为可维护
第二、这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用
第三、此诗若要加字,只需另刻字加入即可,这是可拓展
第四、字的排列其实可能是竖排,可能是横排,此时只需将活字移动就可做的满
   足排列需求,此是灵活性好

1.6面向对象的好处

  1. 通过封装、继承、多态把程序的耦合度降低
  2. 使用设计模式使得程序更加灵活、易于修改,且易于复用

1.7 复制VS复用

思考:要求你再写一个计算器?怎么办?
办法:Ctrl + C / Ctrl + V ?
结论:看似简单,当重复代码多到一定程度,维护的时候,可能就是一场灾难。
思路:分一个类出来,\color{red}{让计算和显示分开}

1.8 业务的封装

准确的说,让业务逻辑界面逻辑分开,让他们直之间的耦合度下降。只有分离开才可以达到容易维护和拓展。

  1. 业务逻辑运算类 【可复用了哦】
public class Opration {
    public static double getResult(double number1, double number2, String op) {
        double result = 0;
        switch(op) {
            case "+" : result = number1 + number2;break;
            case "-" : result = number1 - number2;break;
            case "*" : result = number1 * number2;break;
            case "/" : result = number1 / number2;break;
            default: System.out.println("操作符不合法!");break;
        }
        return result;
    }
}
  1. 客户端代码
//客户端代码
package com.designPattern.v1;

import java.util.Scanner;

public class Cacultor3 {
    public static void main(String[] args) {
        try {
            Scanner scan = new Scanner(System.in);
            double number1 = 0,number2 = 0;
            String op = null,result = null;
            //输入的类型与想要的不符怎么办?
            System.out.println("请输入数字A:");
            if(scan.hasNextDouble()) {
                number1 = scan.nextDouble();
                System.out.println(number1);
            } else {
                throw new Exception("数字类型规范");
            }
            
            System.out.println("请输入符号:+ - * /");
            if(scan.hasNext()) {
                op = scan.next();
            }
                
            System.out.println("请输入数字B:");
            if(scan.hasNextDouble()) {
                System.out.println(number2);
                number2 = scan.nextDouble();
            } else {
                throw new Exception("数字类型规范");
            }
            if(number2 == 0) {
                result = "除数不能为0";
            } else {
                result = Opration.getResult(number1, number2, op) + "";
            }
            System.out.println("结果是 "+ result);
            scan.close();
        } catch(Exception e) {
            System.out.println("您输入的参数不符合规范");
            System.exit(-1);
        }
    }
}

1.9 紧耦合 VS 松耦合

问题:上面的代码是否可以做到灵活地可修改和拓展呢?如果加一个开根
   运算怎么办?改Opration封装类代码吗?改坏了咋办!!!
思考: 如何增加或修改一个算法而不影响算法?
方案: 抽象实现属性封装算法声明,继承实现属性继承和算法分离,多态实现不同算法的切换

package com.designPattern.v1;

import lombok.Data;

@Data
public abstract class Operation {
    private double numberA;
    private double nubmerB;
    public abstract double getResult();
}

class OperationAdd extends Operation {//加法

    @Override
    public double getResult() {
        return getNumberA() + getNubmerB();
    }
}

class OperationSub extends Opration {//减法

    @Override
    public double getResult() {
        return getNumberA() - getNubmerB();
    }
}

class OperationMul extends Opration {//乘法

    @Override
    public double getResult() {
        return getNumberA() * getNubmerB();
    }
}

class OperationDiv extends Opration {//除法

    @Override
    public double getResult() {
        if(getNubmerB() == 0)
            throw new RuntimeException("除数不能为0");
        return getNumberA() / getNubmerB();
    }
}

1.10简单工厂模式

问题:如何让计算器知道我希望用哪一个算法(即如何实例化对象)?
思考:到底要实例化谁?将来会不会增加实例化对象,比如增加开根运行等,这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂

package com.designPattern.v1;

public class OprationFactory {
    
    public static Operation createOperation(String op) {
        Operation2 result = null;
        switch(op) {
            case "+" : result = new OperationAdd();break;
            case "-" : result = new OperationSub();break;
            case "*" : result = new OperationMul();break;
            case "/" : result = new OperationDiv();break;
            default: System.out.println("操作符不合法!");break;
        }
        return result;
    }
}

客户端代码:

Operation2 op = null;
op = OprationFactory.createOperation("+");
op.setNumberA(10);
op.setNubmerB(20);
double result = op.getResult();

编后语

编程是一门技术,更是一门艺术。不能只满足于写完代码,运行结果正确就完事。时常考虑让代码更加简练,更容易维护,容易扩展和复用,只有这样才能真正得到提高。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342