• 设计模式-设计原则


    设计模式-设计原则

    单一职责原则

    单一职责原则:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。

    有时候类的功能并不符合类的定义,添加在类中会使得类过于臃肿,此时应该将职责根据定义进行划分,以实现高内聚低耦合。

    class Coder{
        /**
         * 程序员会编程
         */
        public void coding(){
        }
    }
    class Worker{
        /**
         * 工人会打螺丝
         */
        public void work(){
        }
    }
    class Rider {
        /**
         * 骑手会送外卖
         */
        public void ride(){
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    开闭原则

    开闭原则:软件实体应当对扩展开放,对修改关闭。

    一个软件实体,比如类、模块和函数应该对扩展开放,对修改关闭。其中,对扩展开放是针对提供方来说的,对修改关闭是针对调用方来说的。

    例如以下:

    将程序员打代码这一个行为抽象成一个统一的接口或是抽象类,对具体类行为拓展开放,而具体实现不需要别的类型进行干涉,保证对修改关闭

    public abstract class Coder {
        public abstract void coding();
        class JavaCoder extends Coder{
            @Override
            public void coding() {
                System.out.println("Java!");
            }
        }
        class PHPCoder extends Coder{
            @Override
            public void coding() {
                System.out.println("PHP");
            }
        }
        class CppCoder extends Coder{
            @Override
            public void coding() {
                System.out.println("cpp");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    通过提供一个Coder抽象类,开放给其他具体类型来实现,这样就可以根据不同的业务进行灵活扩展了,具有较好的延续性。

    里氏替换原则

    里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象。

    简单的说就是,子类可以扩展父类的功能,但不能改变父类原有的功能:

    1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
    2. 子类可以增加自己特有的方法。
    3. 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松。
    4. 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或与父类一样。
    public abstract class Coder {
        public void coding() {
        }
        class JavaCoder extends Coder{
            /**
             * 子类除了会打代码之外,还会打游戏
             */
            public void game(){
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    依赖倒转原则

    依赖倒转原则:高层模块不应依赖于底层模块,它们都应该依赖抽象。抽象不应依赖于细节,细节应该依赖于抽象。

    使用接口来进行功能定义,然后再去实现,这样通过使用接口,就可以将原有的强关联给弱化,只需要知道接口中定义了什么方法然后去使用即可,而具体的操作由接口的实现类来完成。

    public class Main {
    
        public static void main(String[] args) {
            UserController controller = new UserController();
        }
    
        interface UserMapper {
            //接口中只做CRUD方法定义
        }
    
        static class UserMapperImpl implements UserMapper {
            //实现类完成CRUD具体实现
        }
    
        interface UserService {
            //业务代码定义....
        }
    
        static class UserServiceImpl implements UserService {
            @Resource   //现在由Spring来为我们选择一个指定的实现类,然后注入,而不是由我们在类中硬编码进行指定
            UserMapper mapper;
            
            //业务代码具体实现
        }
    
        static class UserController {
            @Resource
            UserService service;   //直接使用接口,就算你改实现,我也不需要再修改代码了
    
            //业务代码....
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    接口隔离原则

    接口隔离原则:客户端不应依赖那些它不需要的接口。

    即对接口进行细粒度的划分,确定抽象类的符合功能

    interface SmartDevice {   //智能设备才有getCpu和getMemory
        String getCpu();
        String getType();
        String getMemory();
    }
    interface NormalDevice {   //普通设备只有getType
        String getType();
    }
    //电脑就是一种电子设备,那么我们就继承此接口
    class Computer implements SmartDevice {
    
        @Override
        public String getCpu() {
            return "i9-12900K";
        }
    
        @Override
        public String getType() {
            return "电脑";
        }
    
        @Override
        public String getMemory() {
            return "32G DDR5";
        }
    }
    //电风扇也算是一种电子设备
    class Fan implements NormalDevice {
        @Override
        public String getType() {
            return "风扇";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    合成复用原则

    合成复用原则:优先使用对象组合,而不是通过继承来达到复用的目的。

    如果是is-a的关系可以考虑继承实现,其他情况下进行使用组合去复用方法,减低耦合性

    class A {
        public void connectDatabase(){
            System.out.println("我是连接数据库操作!");
        }
    }
    class B {
        
        A a;
        public B(A a){   //在构造时就指定好
            this.a = a;
        }
        public void test(){
            System.out.println("我是B的方法,我也需要连接数据库!");
            a.connectDatabase();   //也是通过对象A去执行
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    迪米特法则

    迪米特法则:每一个软件单位对其他单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

    简单来说就是,一个类/模块对其他的类/模块有越少的交互越好。当一个类发生改动,那么,与其相关的类需要尽可能少的受影响,利于维护项目。

    public class Main {
        public static void main(String[] args) throws IOException {
            Socket socket = new Socket("localhost", 8080);
            Test test = new Test();
            test.test(socket.getLocalAddress().getHostAddress());  //在外面解析好就行了
        }
    
        static class Test {
            public void test(String str){   //一个字符串就能搞定,就没必要丢整个对象进来
                System.out.println("IP地址:"+str);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    实际上这里的test方法只需要一个IP地址即可,我们完全可以直接传入一个字符串,而不是整个Socket对象,保证与其他类的交互尽可能的少。

  • 相关阅读:
    运行jupyter lab时遇到代码变蓝并且无法运行的问题
    进程间通信(27000字超详解)
    Vue选项: Methods方法
    如何使用docker快速部署MinDoc文档系统
    QT - 简易画板
    JUC并发编程学习(五)集合类不安全
    云原生Docker容器管理
    spline本地运行的方法
    JavaScript编程基础 – 函数进阶
    好记性不如烂笔头(ubuntu的samba的配置)
  • 原文地址:https://blog.csdn.net/CS_z_jun/article/details/134317602