• 设计模式的七大原则(1) --单一职责原则


    前言

    最近工作中备受打击,之前设计的很多程序都被老大否决,需要重构,让我好好看看设计模式。之前对这一块内容的确不怎么重视,感觉枯燥无聊又派不上用场。后来沉下心来研究了一番...

    我靠,原来如此,之前写代码的时候怎么这么傻逼,很多问题其实在一开始设计的时候就能避免。之前写的都是些什么鬼。

    我们踩过的坑,历代前辈们也踩过。可想而知,通他们多年的踩坑填坑经验后,所总结出来的23种设计模式是多么的宝贵,就是我们的“ONE PIECE” 啊。如果掌握了这个内容,对今后无论是工作中还是面试都非常重要。因此下定决心,一定要熟练掌握这块内容。记录学习过程,供自己复习也供大家一起学习。

    为什么要学习设计模式的目的

    在前言中我们已经大致说明,我们总结一下,一个良好的程序应该满足一下六点要求:

    1. 可复用性:尽量能重用方法,比如说提取某种工具类。
    2. 可读性:编程具备规范性,阅读起来不困难。
    3. 可扩展性:当你写好的程序需要添加一个新功能的时候,不能说:不行!非要添加的话我要重构代码。
    4. 稳定性:尽可能少的bug。
    5. 高内聚:每个模块尽可能独立完成自己的功能,不依赖于模块外部的代码。
    6. 低耦合:并且模块之间联系越复杂耦合度越低,就不会牵一发而动全身。否则模块A的bug甚至会导致模块B无法运行
    

    这是多代前辈们总结出来的编程经验,如果我们的程序没有以上特点,就会出现很多BUG。我们要站在巨人的肩膀上。尽量多学习多总结,避免犯“古人”们常犯的错误。

    设计模式的作用就出来了,设计模式的目的就是为了让我们的程序具备以上六点特性。

    设计模式常用的七大原则

    在学习设计模式之前,为了不让设计模式显得很模式,我们还必须了解一个东西,那就是程序设计七大原则(很多地方说的是六大原则,但还有一个合成复用原则也值得提出来)。

    这些原则是指导模式的规则,我会给一些原则附上一个例子,来说明这个原则所要表达的意思,注意,原则是死的,人是活的,所以并不是要你完完全全遵守这些规则,否则为何数据库会有逆范式,只是在可能的情况下,请尽量遵守。

    七大原则分别是:

    1. 单一职责原则(Single Responsibility Principle)
    2. 接口隔离原则(Interface Segregation Principle)
    3. 依赖倒置原则(Dependence Inversion Principle)
    4. 里氏替换原则(Liskov Substitution Principle)
    5. 开闭原则(Open Close Principle)
    6. 迪米特法则(Law Of Demeter)
    7. 合成复用原则(Composite/Aggregate Reuse Principle CARP)
    

    单一职责原则

    看名字就能知道,我们设计的类要尽可能的只负责一项职责。比说说A类只负责A功能,B类只负责B功能,不要A类既负责A功能又负责B功能。

    为什么要这样设计?

    当A功能需要更新,那么就得去修改A类。如果此时A还负责B功能,就很有可能修出BUG后导致B功能的正常使用。或者说,想实现B功能却调用的A功能的接口,这样会导致程序运行混乱。总结以下几点:

    1. 降低类的复杂度,一个类只负责一项职责。
    2. 提高类的可读性,可维护性。
    3. 降低变更引起的风险。
    4. 通常情况下,我们应当遵守单一职责原则,只要逻辑足够简单,才可以在代码级别违反单一职责原则:也就是说类中的方法数量足够少,可以在方法级别保持单一职责原则。下述代码将会说明。
    

    例如以下代码:

    public class SingleResponsibility1 {
        public static void main(String args[]) throws IOException {
            Computer computer = new Computer();
            computer.add();
        }
    
    }
    //读取配置文件和计算
    class Computer{
        public int add() throws NumberFormatException, IOException {
            File file = new File("D:/data.txt");
            BufferedReader br = new BufferedReader(new FileReader(file));
            int a = Integer.valueOf(br.readLine());
            int b = Integer.valueOf(br.readLine());
            return a+b;
        }
    }
    

    在这个Computer类中有一个add方法,负责读取配置文件数字,然后再进行相加。

    这个类很明显违反了单一职责原则,一个类既负责了读取文件,又负责算数。大家考虑一下这样设计有没有什么问题?

    问题诸多,提高代码可维护性,报错不好定位,功能耦合。。。

    来看看更新后的代码是什么样子的:

    public class SingleResponsibility2 {
        public static void main(String args[]) throws IOException {
            readFile readFile = new readFile();
            readFile.read("D:/data.txt");
            Computer2 computer = new Computer2();
            computer.add(readFile.getA(),readFile.getB());
        }
    
    }
    //计算
    class Computer2 {
        public int add(int a, int b){
            return a + b;
        }
    }
    //读取配置文件
    class readFile {
        private int a;
        private int b;
    
        public void read(String path) throws IOException {
            File file = new File(path);
            BufferedReader br = new BufferedReader(new FileReader(file));
            a = Integer.valueOf(br.readLine());
            b = Integer.valueOf(br.readLine());
        }
    
        public int getA() {
            return a;
        }
    
        public int getB() {
            return b;
        }
    }
    

    通过这样修改代码,我们实现了单一职责原则。

    这样就万无一失了吗?

    当然有时候也不见得,因为如果我们的代码足够简单,这样设计会提供编写代码的成本。并且同时还要修改客户端代码。

    我们再来看看下面的代码:

    public class SingleResponsibility3 {
        public static void main(String args[]) throws IOException {
            Computer3 computer = new Computer3();
            computer.read("D:/data.txt");
            computer.add(computer.getA(),computer.getB());
        }
    
    }
    //负责读取配置文件,并且负责计算
    class Computer3 {
        private int a;
        private int b;
    
        public void read(String path) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader(path));
            a = Integer.valueOf(br.readLine());
            b = Integer.valueOf(br.readLine());
        }
    
        public int getA() {
            return a;
        }
    
        public int getB() {
            return b;
        }
        
        public int add(int a, int b){
            return a + b;
        }
    }
    
    

    当然这个只是示例代码,在真正的开发环境也不可能这样用。我举这个例子只是想说明如果一个类的方法很少功能逻辑比较简单。如我们写的Computer类,只负责读取两个数,然后相加。

    这样简单的类其实就可以在代码级别违反单一职责原则:也就是说类中的方法数量足够少,可以在方法级别保持单一职责原则。

    还是那句话:人是活的,原则是死的。

    一个优秀的代码if else应该尽量的少用,要不耦合会非常严重,去看看优秀源码也是如此。可以思考思考使用单一职责原则,用类来划分多分支。

    总结

    今天就到这里,一个一个慢慢吃透,一天进步一点。下一篇我们来看接口隔离原则。

  • 相关阅读:
    拓扑排序笔记
    最小生成树——垃圾佬抓宠物
    次小生成树
    关于 海平面上升 与 fold的毒瘤题(easy) 的思考
    看正月点灯笼老师的笔记—01背包
    欧拉图的判定欧拉路的求法
    离散实验——关系闭包运算
    Floyd 求最短路
    离散实验——二元关系及其性质
    最小生成树
  • 原文地址:https://www.cnblogs.com/zhxiansheng/p/11212355.html
Copyright © 2020-2023  润新知