设计模式-设计原则与设计模式总结

设计原则,是设计模式的基础。在实际开发中,并不是一定要求所有代码都遵循设计原则,我们需要综合考虑人力、时间、成本、质量,不是可以追求完美,要在设当的场景遵循合适的设计原则,体现的是一种平衡取舍,帮助我们设计出更加优雅的代码结构。

设计模式(Design Pattern)是前辈们经过相当长的一段时间的试验和错误总结出来的,是软件开发过程中面临的通用问题的解决方案。这些解决方案使用设计模式是为了解耦,可重用代码、让代码更容易被他人理解、保证代码可靠性。

不用设计模式并非不可以,但是用好设计模式可以帮助我们更好的解决实际问题。设计模式最重要的是解耦。一般而言,我们在实际开发中某一个业务功能不会只使用一种设计模式,而是多个设计模式结合,你中有我,我中有你。

设计模式的初衷,主要是为了随着业务需求的变化与增加,减少对原代码的更改,易于扩展,做到代码解耦。同时让代码看起来更加优雅,易于复用。但是也带来了一些问题,比如设计花费更多的时间,理解起来更加复杂,代码量也会随之增加。

学习设计原则与设计模式,也是锻炼我们将业务需求转换成技术实现的一种非常有效的方式。而且很多优秀的框架,都大量使用了设计模式,如果我们没有学习,则不容易读懂代码。很多源码,通过变量或方法命名即可了解使用的设计模式。

设计原则

  • 开闭原则Open-Closed Principle:对扩展开放,对修改关闭
    它是指一个软件实体,如类,模块,函数等应该对扩展开放,对修改关闭。它强调的是用抽象构建框架,用实体扩展细节,可以提高软件系统的可复用性与可维护性。
  • 依赖倒置原则Dependence Inversion Principle:通过抽象使各个类或者模块互不影响,实现松耦合
    它是指在设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖其抽象。抽象不应该依赖细节。通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并能够降低修改程序所造成的风险。
  • 单一职责原则Simple Responsibility Principle:一个类、接口、方法只做一件事
    它是指不要存在多于一个导致类变更的原因。
  • 接口隔离原则Interface Segregation Principle:尽量保证接口的纯洁性,客户端不应该依赖不需要的接口
    它是指使用多个专门的接口,而不使用单一的总接口。这个原则指导我们在设计接口时应注意以下几点:
    • 一个类对一类的依赖应该建立在最小的接口之上
    • 建立单一接口,不要建立庞大臃肿的接口
    • 尽量细化接口
  • 迪米特法则Law Of Demeter:又叫最少知道原则,一个类对其所依赖的类知道的越少越好
    它是指一个对象应该对其他对象保持最少的了解,尽量降低类与类之间的耦合。迪米特法则主要强调只和朋友交流,不和陌生人说话。
  • 里氏替换原则Liskov Substitution Principle:子类可以扩展父类的功能但不能改变父类原有的功能
    它是指如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
  • 合成复用原则Composite/Aggregate Reuse Principle:尽量使用对象组合、聚合,而不使用继承关系达到代码复用的目的
    它是指尽量使用对象组合has-a或聚合contains-a,而不是继承关系达到软件复用的目的。可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少。

设计模式

  • 创建型:类的创建。
    对类的实例化进行了抽象,能够使软件模块做到与对象的创建和代码组织无关。
    包含5种:工厂方法模式,抽象工厂模式,建造者模式,单例模式,原型模式。其中原型模式基本不用自己造轮子。
  • 结构型:组合代替;类与类之间的关系;
    描述类与对象之间如何进行有效地组织,以形成良好的软件体系结构,主要的方式是使用继承关系来组织各个类。
    包含7种:适配器模式,装饰器模式,代理模式,门面模式,组合模式,享元模式,桥接模式。其中桥接模式自己造轮子的可能性比较低。
  • 行为型:关注对象与行为的分离,就是要把行为分离到类里面
    描述类和对象之间如何交互以及如何分配职责。
    包含11种:策略模式,观察者模式,责任链模式,解释器模式,模板方法模式,迭代器模式,中介者模式,命令模式,访问者模式,备忘录模式,状态模式。其中观察者模式,解释器模式,迭代器模式,中介者模式,命令模式,访问者模式与备忘录模式基本不用自己造轮子。
工厂模式
  • 简单工厂模式:它是指由一个工厂对象决定创建出哪一种产品类的实例。
  • 工厂方法模式:它是指定义一个创建对象的接口,但是让实现这个接口的类决定实例化那个对象。
  • 抽象工厂模式::它是指提供一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类,客户端不依赖于产品类实例如何被创建、实现等细节强调的是一系列相关的产品对象一起使用创建对象需要大量重复的代码。
    个人理解是适合创建两个维度的对象,一个维度是工厂维度,比如,格力工厂,美的工厂,另一个维度是产品类别,比如格力工厂创建格力冰箱,格力空调。。。
单例模式

目的:保证独一无二
源码:Calender,Runtime
面试题:可能出现单例被破坏的情况

  • 多线程(双检锁与静态内部类)
  • JVM指令重排(使用volitile)
  • 克隆(重写clone方法)
  • 反序列化(重写readResolve方法,返回单例)
  • 反射(枚举,构造方法中设置)
原型模式

目的:高效创建对象
源码:ArrayList,PrototypeBean
浅克隆方法:工具类BeanUtils与PropertyUtils;实现clonable接口等
深克隆方法:每个对象实现Cloneable接口并重写clone方法;序列化;Apache-commons包的SerializationUtils.clone(T obj);json工具;构造方法手动new对象

建造者模式

目的:开放个性配置步骤
源码:StringBuilder,BeanDefinitionBuilder
核心思想:实现零件的无序装配。

代理模式

目的:增强职责
源码:ProxyFactoryBean,JdkDynamicAopProxy,CglibAopProxy
代理对象在客户端与目标对象之间起到中介作用。保护目标对象,增强目标对象功能。

动态代理的基本实现:

  • 拿到被代理类的引用,并且获取它的所有接口
  • 重新生成一个新的类,实现或重写需要代理的方法
  • 动态生成代码,并把增强逻辑加入其中
  • 编译新代码
  • 加载运行

Cglib与JDK动态代理对比:

  • jdk动态代理实现被代理对象的接口,CGLIB继承被代理对象
  • 二者都是在运行期生成字节码
  • JDK动态代理是通过反射机制调用代理方法,CGLIB是通过FastClass机制
  • CGLIB无法代理final修饰的方法(因为无法重写该方法)
门面模式

目的:统一访问入口
源码:JdbcUtils,RequestFacade

装饰器模式

目的:灵活扩展,同宗同源
源码:BufferedReader,InputStream
基本实现方法:一个抽象类,基础类和各包装类继承抽象类,并持有引用。使用时相当于下一步的持有上一步结果的引用,对上一步结果进行重写(增强),从而达到灵活扩展的目的。

享元模式

目的:共享资源池
源码:String ,Integer, ObjectPool

组合模式

目的:统一整体和个体
源码:HashMap,SqlNode

适配器模式

目的:兼容转换
源码:AdvisorAdapter, HandlerAdapter

桥接模式

目的:不允许使用继承
源码:DriverManager

委派模式

目的:只对结果负责
源码:ClassLoader,BeanDefinitionParserDelegate

模板方法模式

目的:流程标准化,步骤微调;逻辑复用
源码:JdbcTemplate,HttpServlet

策略模式

目的:把选择算法的权力交给用户
源码:Comparator,InstantiationStrategy

责任链模式

目的:解耦处理的逻辑
源码:Filter Chain,Pipeline

迭代器模式

目的:统一对集合的访问方式
源码:Iterator

命令模式

目的:解耦请求和处理
源码:Runnable,TestCase

状态模式

目的:绑定状态和行为
源码:Lifecycle

备忘录模式

目的:备份
源码:StateManageableMessageContext

中介者模式

目的:统一管理网状资源
源码:Timer

解释器模式

目的:实现特定语法解析
源码:Pattern,ExpressionParser

观察者模式

目的:解耦观察者与被观察者
源码:ContextLoaderListener

访问者模式

目的:解耦数据结构与数据操作
源码:FileVisitor,BeanDefinitionVisitor

欢迎大家留言,以便于后面的人更快解决问题!另外亦欢迎大家可以关注我的微信公众号,方便利用零碎时间互相交流。共勉!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738231.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mirai Bot初始化配置

RT其实本来我的bot已经因为自己手贱登陆qq nt直接报废了,但是论坛里有佬提供了新的协议库,那这不赶紧复活bot都对不起这个新的协议库。 本文写于2024年7月4日19:20:21,可能随着时间久远而无法实现功能。由于存在下载障碍,所以这里也搞了个存档,本帖中的相关标星*资源无法下…

量化曲线的平滑程度

思路 1. 对原始数据一阶求导,得到一阶导数数组。 2. 对一阶导数数组求标准差。导数的标准差提供了导数值的波动性,标准差越小,曲线越平滑。 平滑曲线import numpy as np import matplotlib.pyplot as plt from matplotlib import font_manager fname="/usr/local/pytho…

Android常见错误

错误1 A problem occurred configuring root project ����ʶ��. > Could not resolve all files for configuration :classpath.> Could not resolve com.android.tools.build:gradle:8.4.0.Required by:project : > com.android.application:com.android.appli…

MyBatis中的Where标签:提升你的SQL查询效率

哈喽,大家好,我是木头左!理解MyBatis的Where标签 MyBatis是一款优秀的持久层框架,它提供了许多强大的标签来帮助编写更优雅、高效的SQL语句。其中,<where>标签是使用频率极高的一个,它能够自动处理查询条件,使得的SQL语句更加简洁和高效。在这篇文章中,将深入探讨…

Java中的JSON神器,如何轻松玩转复杂数据结构

哈喽,大家好,我是木头左!一、揭秘JSON世界的基石 在Java的世界中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于文本,易于阅读和编写,同时也易于机器解析和生成。JSON在日常开发中的应用非常广泛,无论是前后端的数据交互,还是配置文件的读取,…

《Python 第三方模块包安装指南》

在 Python 编程中,第三方模块包极大地丰富了其功能,让我们能够更高效地完成各种任务。下面将为您详细介绍如何安装 Python 的第三方模块包。 一、使用 pip 命令安装 pip 是 Python 的包管理工具,大多数情况下,我们可以通过以下命令来安装第三方模块包:pip install 模块包名…

巴图自动化Modbus转PN网关模块连智能仪表与PLC通讯

通过巴图自动化Modbus转Profinet协议网关模块,实现PLC对仪表设备的远程监控和数据传输,提高生产效率和运行稳定性。巴图自动化Modbus转Profinet协议转换BT-MDPN100网关模块的主要功能是实现Modbus协议和Profinet协议之间的转换和通信。Modbus 转 Profinet协议网关模块集成了M…

一文搞懂到底什么是 AQS

日常开发中,我们经常使用锁或者其他同步器来控制并发,那么它们的基础框架是什么呢?如何实现的同步功能呢?本文将详细用白话讲解构建锁和同步器的基础框架--AQS,并根据源码分析其原理。前言 日常开发中,我们经常使用锁或者其他同步器来控制并发,那么它们的基础框架是什么…

flutter状态管理 provider使用

provider是flutter官方推荐的状态管理插件,是基于InheritedWidget实现的。 下面我们来讲一个provider的使用方法。 1.在pubspec.yaml文件中添加 provider: ^6.1.2 开发文档:https://pub-web.flutter-io.cn/packages/provider 可以查看使用方法和最新版本号。 添加完成后…

企业数字化转型:顶层规划方法

随着数字化时代的到来,发生了以数字化、智能化为典型特征的新一轮科技革命,各行各业利用互联网、大数据、云计算、人工智能、区块链技术对传统产业进行全方位、全链条改造,实施“上云用数赋智”行动,全面推进各行业数字化转型。数字经济的大门已然开启,数字经济顶层战略规…

Nuxt3 的生命周期和钩子函数(十)

摘要:本文详细介绍了Nuxt3框架中的五个webpack钩子函数:webpack:configResolved用于在webpack配置解析后读取和修改配置;webpack:compile在编译开始前调用,可修改编译选项;webpack:compiled在编译完成后调用,可处理编译结果;webpack:change在开发模式下文件变化时触发,…

Jenkins汉化

1、Jenkins版本:版本2.426.3) Manage Jenkins->选择Plugins->切换到Availabled plugin->搜索local,然后选中安装,如下图所示 2、安装完成后重启Jenkins,汉化完成。如下图所示 像个小学生一样努力学习