面向对象设计模式之概念

一、面向对象设计模式

  • 按目的分为创建型(creational)结构型(structural)行为型(behavioural)
  • 按范围分为类模式对象模式

二、设计原则

        两大基础设计原则
  • 程序设计的原则:模块内高内聚,模块间低耦合
  • 开闭原则:开闭原则是面向对象的可复用设计的第一块基石,是最重要的面向对象设计原则。(十个字概括:对扩展开放,对修改关闭),也就是避免添加修改代码。
        从基础原则出发,产生六个具体的原则

        六大原则的目的:1)提高软件的可维护性(maintainability):指软件能够被理解、改正、适应及扩展的难易程度;2)可复用性(Reusability):之软件能够被重复使用的难易程度;

        面向对象设计的目标之一:在于支持可维护性复用,一方面需要实现设计方案或者源代码的复用、另一方面要确保系统能够易于扩展和修改,具有良好的可维护性。面向对象设计原则为支持可维护性复用而诞生指导性原则,非强制性原则。每一个设计模式都符合一个或多个面向对象设计原则,面向对象设计原则是用于评价一个设计模式的使用效果的重要指标之一。

  • (1) 单一职责原则
    • 单一职责原则(Single Responsibility Principle SRP ):是最简单的面向对象设计原则,用于控制类的粒度大小。(一个方法或一个类只做一件事,为了模块内高内聚)
    • 定义:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。就一个类而言,应该仅有一个引起它变化地原因。
    • 单一原则分析:
      • 1.一个类(大到模块,小到方法)承担的指责越多,它被复用的可能性就越小;
      • 2.当一个职责变化时,可能会影响其他职责的运作;
      • 3.将这些职责进行分离,将不同的职责封装在不同的类中;
      • 4.将不同的变化原因封装在不同的类中;
      • 5.单一职责原则是实现高内聚,低耦合的指导方针。
  • (2) 迪米特法则
    • 迪米特法则定义(LOD):又叫做最少知识原则(LKP),每一个软件单位对其他的单位都只是最少的知识,而且局限于那些与本单位密切相关的软件。(也叫最少知道原则,为了模块间低耦合)
    • 迪米特法则分析:要求一个软件实体应当尽可能地与其他实体发生相互作用。应用迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。
      • 1.迪米特法则要求在设计系统时,应该尽量减少对象之间的交互;
      • 2.如果两个对象之间不必彼此直接通信,那么这两个对象就不应该发生任何直接的相互作用;
      • 3.如果其中一个对象需要调用另一个对象的方法,可以通过“第三者”转发这个调用;
      • 4.通过引入一个合理的“第三者”来降低现有对象之间的耦合度。
  • (3) 里氏替换原则
    • 定义:所有引用基类的地方必须能透明地使用其子类对象。(就是继承原则,子类可以无缝替代父类。很好的符合了开闭原则)
    • 通俗概念:在一个软件系统中,子类应该可以替换任何基类能够出现的地方,并且经过替换以后,代码还能正常工作。
    • 继承的优点:
      • 1.子类拥有父类所有的方法和属性,从而减少创建类的工作量;
      • 2.提高了代码的重用性;
      • 3.提高了代码的扩展性,子类不但拥有了父类的所有功能,还可以添加自己的功能。
    • 继承的缺点:
      • 1.继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
      • 2.降低了代码的灵活性。因为继承时,父类会对子类有一种约束;
      • 3.增强了耦合性。当需要对父类的代码进行修改时,必须考虑到对子类产生的影响。有时修改了一点点代码都可能需要对打断程序进行重构。
    • 里氏代换原则(继承的扬长避短)LSP:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换o2时,程序P的行为没有变化,那么类型S时类型T的子类型。里氏替换原则堆积成进行了规则上的约束
      • 1.子类必须实现父类的抽象方法,但不得重写(覆盖)父类得非抽象(已实现)方法;
      • 2.子类中可以增加自己特有得办法;
      • 3.当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松;
      • 4.当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
    • 里氏替换原则时实现抽象化的一种规范。违反里氏替换原则意味着违反了开闭原则,反之未必
  • (4) 依赖倒置原则
    • 依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。其核心思想是:要面向接口编程,不要面向实现编程。(类之间的依赖通过接口实现,低耦合的同时对扩展开放)
    • 依赖倒置原则(DIP)的原始定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象
    • 依赖倒转原则分析:
      • 1.在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数声明、方法类型声明,以及数据类型的转换等。
      • 2.在程序中尽量使用抽象进行编程,而将具体类写在配置文件中。
      • 3.针对抽象层编程,将具体的对象通过依赖注入(Dependency Inection,DI)的方式注入到其他对象:构造注入、设值注入(Setter注入)、接口注入。
    • 依赖倒置原则的主要作用如下:
      • 1.依赖倒置原则可以提高系统的稳定性;
      • 2.依赖倒置原则可以减少并行开发引起的风险;
      • 3.依赖倒置原则可以提高代码的可读性和可维护性;
      • 4.依赖倒置原则可以降低类间的耦合性。
    • 依赖倒置原则的目的是通过要面向接口的编程来降低类间的耦合性,所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。
      • 1.每个类尽量提供接口或抽象类,或者两者都具备;
      • 2.变量的声明类型尽量是接口或者是抽象类;
      • 3.任何类都不应该从具体类派生;
      • 4.使用继承时尽量遵循里氏替换原则。
  • (5) 接口隔离
    • ​​​​​接口的定义1:一个类型所提供的所有方法特征的集合,一个接口代表一个角色,每个角色都有它特定的一个接口,“角色隔离原则”。(即把单个复杂接口拆分为多个独立接口,与上条共同实现面向接口编程)
    • 接口的定义2:狭义的特定语言的接口。接口仅仅提供客户端需要的行为,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独接口,而不是提供大的总接口,每个接口中只包含一个客户端所需的方法,“定制服务”。
    • 接口隔离原则:客户端不应该依赖那些它不需要的接口(ISP)。类间的依赖关系应该建立在最小的接口上,它要求是最小的接口,也是要求接口细化,接口纯洁。
    • 接口隔离原则分析:
      • 1.当一个街头太大时,需要将它分割成一些更细小的接口;
      • 2.使用该接口的客户端仅需知道与之相关的方法即可;
      • 3.每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。
    • 采用接口隔离原则约束接口注意事项:
      • 1.接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不争的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度;
      • 2.为依赖接口的类指定服务,只暴露给调用的类他需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系;
      • 3.提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情;
    • 接口隔离原则与单一职责原则比较:类和接口职责单一,注重的使职责,是业务逻辑的划分。而接口隔离原则需要接口的方法尽量少。
  • (6) 合成复用原则
    • 合成复用原则定义:又叫组合/聚合复用原则CARP/CRP,优先使用对象组合,而不是继承来达到复用的目的。(即尽量使用合成/聚合的方式,而不是使用继承。主要为了防止继承滥用而导致的类之间耦合严重。记住只有符合继承原则时才用继承)
    • 合成复用原则分析:
      • 1.合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;
      • 2.新对象通过委派调用已有对象的方法达到复用功能的目的;
      • 3.复用时要尽量使用组合/聚合关系(关联关系),少用继承。
    • 继承复用:实现简单,易于扩展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。(“白箱”复用)
    • 组合/聚合复用:耦合度相对较低,有选择性地调用成员对象的操作;可以在运行时动态进行,新对象可以动态地引用与成员对象类型相同的其他对象。(“黑箱”复用)

三、UML

        UML中类之间的关系:根据类与类之间的耦合度从弱到强排列,UML中的类图有以下几种关系:依赖、关联、聚合、组合、泛化、实现关系。其中泛化和实现的耦合度相等,他们是最强的。(各种关系的强弱顺序:泛化=实现>组合>聚合>关联>依赖)

  • 1.依赖关系(Dependency):是一种使用关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依赖。
    • 代码实现:局部变量、方法的参数或者对静态方法的调用
    • 箭头及指向:带箭头的虚线,指向被使用者。

  • 2.关联关系(association):是对象之间的一种引用关系,用于表示一类知道另一个类的属性和方法。对象与另一类对象之间的联系。使一个类关联关系西是类与类之间常用的一种关系,分为一般关联关系、聚合关系和组合关系。比如:老师与学生,丈夫与妻子。
    • 代码实现:成员变量。
    • 箭头及指向:带箭头的实心线,如果是双向关联就是实心线。

  • 3.聚合(Aggregation)关系:使整体与部分的关系,且部分可以离开整体而单独存在。has-a的关系。
    • 聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。
    • 代码实现:成员变量
    • 箭头及指向:带空心菱形的实心线,菱形指向整体。

  • 4.组合(compositon)关系:是整体与部分的关系但部分不能离开整体而单独存在。
    • 代码实现:成员变量
    • 箭头及指向:带实心菱形的实线,菱形指向整体。
    • 组合关系和聚合关系比较:
      • 1.聚合与组合都是一种结合关系,具有整体-部分的意义。
      • 2.部件的生命周期不同。(聚合关系中,整件不会拥有部件的生命周期,所以整件删除时,部件不会被删除。再者,多个整件可以共享同一个部件。组合关系中,整件拥有部件的生命周期,所以整件删除时,部件一定会跟着删除。而且,多个整件不可以同时间共享一个部件。)
      • 3.聚合关系是“has-a”关系,组合关系是"contains-a"关系。

  • 关联和依赖:
    • 1.关联关系中,体现的是两个类、或者类与接口语义级别的一种强依赖关系,比如我和我的朋友;这个关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的们一般是长期性的,而且双方的关系一般是平等的。
    • 2.依赖关系中,可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是B类的变化会影响到A。
  • 5.泛化(Generalization)关系:是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是is-a的关系
    • 箭头及指向:带空心三角箭头的实线来表示,箭头从子类指向父类。

  • 6.实现(Realization)关系:是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。
    • 箭头及指向:带空心三角箭头的虚线来表示,箭头从实现类指向接口。

如何利用Eclipse画UML?--->>>需要安装AmaterasUML插件。

1.导航栏点击帮助(help),选择Install New Software安装新软件 

2.输网址:https://takezoe.github.io/amateras-update-site/,点击添加(Add)

3.点击全部选中(SelectAll)全选,一直点Next和接受

注:下载失败的话,可能与网络环境有关,多试几次 

4.下载成功后重启Eclipse,就可以画类图了

5.选择想要生成UML图类,选择文件->>>新建(new)->>>选择其他(Other)找到Class Diagram新建,然后就把想要画的类拖入即可

四、设计模式

4.1 行为型模式(即方法及其调用关系)
  • Observer:观察者模式(用订阅-发布实现的被观察者变化时回调)
  • Strategy:策略模式(提供功能不同实现方式,且实现可选)
  • Template Method:模板方法模式(相同流程用一个模板方法)
  •  Iterator:迭代器模式(一种内部实现无关的集合遍历模式)
  • Chain of Responsibility:责任链模式(事件处理的分层结构产生的责任链条)
  • Command:命令模式(将命令者与被命令者分离)
  • Memento:备忘录模式(需要撤销与恢复操作时使用)
  • State:状态模式 (当对象两种状态差别很大时使用)
  • Visitor:访问者模式 (当对同一对象有多种不同操作时使用)
  • Mediator:中介者模式(以中介为中心,将网状关系变成星型关系)
  • Interpreter:解释器模式(常用于纯文本的表达式执行)
4.2 创建型模式(IOC:控制反转,就是创建分离的集大成)
  • Factory Method:工厂方法模式(对象创建可控,隐藏具体类名等实现解耦)
  • Abstract Factory:抽象工厂模式(解决对象与其属性匹配的工厂模式)
  • Builder:建造者模式(封装降低耦合,生成的对象与构造顺序无关)
  • Singleton:单例模式(全局只要一个实例)
  • Prototype:原型模式(通过拷贝原对象创建新对象)
  • 创建型模式的五种有各自的使用环境,单例和原型比较简单就不说了,工厂方法模式和建造者模式,都是封装和降低耦合有啥不同呢,其实工厂方法关注的是一个类有多个子类的对象创建(汽车类的各种品牌),而建造者模式关注的是属性较多的对象创建(能达到过程无关)。而抽象工厂模式关注的是对象和属性及属性与属性的匹配关系(如奥迪汽车与其发动机及空调的匹配)。
4.3 结构型模式(对象的组成以及对象之间的依赖关系)
  • Adapter:适配器模式(适配不同接口和类,一般解决历史遗留问题)
  • Decorator:装饰器模式(比继承更灵活,可用排列组合形成多种扩展类)
  • Proxy:代理模式(可以给类的每个方法增加逻辑,如身份验证)
  • Facade:外观模式(对模块或产品的封装,降低耦合)
  • Bridge:桥接模式(就是接口模式,抽象与实现分离)
  • Plyweight:享元模式(相同对象的重用)
  •  Composite:组合模式(整体和部分相同时,如文件夹包含文件夹)
  •  我们可以看到适配器模式、装饰器模式、代理模式都可以用包装对象来实现(把对象作为一个属性放在用的对象里),所以模式关注的并不是实现,而是解决的问题。模式更多体现的是类与类之间的逻辑关系,比如代理模式和装饰器模式很像。但从字面就知道,代理是访问不了实际工作对象的,这是他们的区别。

这里借鉴了面向对象的23种设计模式博客。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

electron项目打包慢、打包报错

项目使用了electron框架,在第一次打包或者网络条件不好的环境下进行打包时熟速度慢的出奇,甚至经常出现打包失败的情况(如上面图片的报错)。 这是因为,在electron打包的过程中,需要去官方源https://github.…

安卓手机怎么连接电脑?这三个方法即刻解决!

随着智能手机的普及,我们越来越依赖手机进行工作和娱乐。然而,有时候我们需要将手机上的数据或文件传输到电脑上,或者需要在电脑上进行某些操作。那么,安卓手机怎么连接电脑呢?这篇文章将为你介绍三种简单的方法&#…

车载摄像头画质增强解决方案,赋能智能驾驶新时代

在智能化浪潮席卷汽车产业的今天,车载摄像头作为智能驾驶的“眼睛”,其画质清晰度直接关系到车辆感知环境的准确性和驾驶的安全性。然而,面对复杂多变的行车环境,如何确保车载摄像头在不同场景下都能呈现出高质量的图像&#xff0…

OpenHarmony轻量系统开发【1】初始OpenHarmony

1.1系统类型 OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,基于开源的方式,搭建一个智能终端设备操作系统的框架和平台,促进万物互…

mac使用docker部署confluence

第一步拉镜像 选择7.13.6 点击pull 在镜像出 创建容器 并配置映射 需要等待一会 浏览器访问 confluence 服务 http://localhost:8090/ 语言选择中文 复制服务器ID 然后停止docker 容器 BBN3-O8RH-XJPI-GYAA 复制docker中confluence的系统文件 进入Files 考文件 文件目录…

基于springboot实现在线考试系统设计【项目源码+论文说明】

基于springboot实现在线考试管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于JavaWeb技术的在线考试系统设计与实现的开发全过程。通过分析基于Java Web技术的在线考试系统设计与实现管理的不…

vue给页面添加水印

vue给页面添加水印 <template><div class"home"><router-view /></div> </template><script>export default {components: {},data() {return {}},computed: {},mounted() {// 获取需要观察的节点const target document.queryS…

【DM8】ET SQL性能分析工具

通过统计SQL每个操作符的时间花费&#xff0c;从而定位到有性能问题的操作&#xff0c;指导用户去优化。 开启ET工具 INI参数&#xff1a; ENABLE_MONITOR1 MONITOR_SQL_EXEC1 查看参数 select * FROM v$dm_ini WHERE PARA_NAMEMONITOR_SQL_EXEC;SELECT * FROM v$dm_ini WH…

sky08、09笔记常用组合逻辑电路

本节的目的是为了更好的预估delay。 1.1bit全加器 module fadd_1b( a, b, cin, s, cout ); input wire a,b,cin; output wire s,cout;wire p,g; assign p a|b;//propagate carry assign g a&b;//generate carry assign s a^b^cin; assign cout (p&cin)|g; endmodu…

c++的学习之路:19、模板

摘要 本章主要是说了一些模板&#xff0c;如非类型模板参数、类模板的特化等等&#xff0c;文章末附上测试代码与导图 目录 摘要 一、非类型模板参数 二、类模板的特化 1、概念 2、函数模板特化 3、类模板特化 三、模板的分离编译 1、什么是分离编译 2、模板的分离编…

一次网卡驱动BUG故障的排错历程

前言 在日常运维中&#xff0c;总会遇到一些棘手的故障或问题&#xff0c;尤其面临多系统融合的兼容性或一些融合节点可能存在未知bug等方面&#xff0c;排错难度都会增加。 本文将从一次小事件为入口进行延伸&#xff0c;将宿主机esxi基础系统的多融合节点故障的排错历程展开…

分布式监控平台---Zabbix

一、Zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监控软件&#xff0c;我们可以&#xff1a; 通过一个友好的界面进行浏览整个…

C/C++ C/C++ 入门(6)模板初阶

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 多多指教&#xff01; 一、泛型编程 在之前&#xff0c;我们进行编程的时候&#xff0c;总是针对于某一个具体的问题。就比如说&#xff0c;如何实现一个int类型的swap函数呢&#xff1f;大家肯定会写。…

MySQL 表管理

目录 建库 语法&#xff1a; 库名命名规则&#xff1a; 相关命令&#xff1a; 建表 语法&#xff1a; 相关命令&#xff1a; 修改表 语法&#xff1a; 常用操作命令 复制表 数据类型 MySQL的10种常用数据类型&#xff1a; 数据的导入和导出 导入&#xff1a; 格…

iptables 学习

文章目录 iptables 学习iptables基本组件&#xff1a;常用iptables命令&#xff1a;iptables -L 输出及解释解释&#xff1a; iptables “奇淫巧技”端口转发&#xff08;port forwarding&#xff09;流量重定向到透明代理防止DDoS攻击防止SYN洪泛攻击黑名单使用状态模块跟踪连…

第14届java A组蓝桥杯做题记录

A题 特殊日期 package Java14省赛.Java研究生组;import java.time.Year; //特殊判断一下2月份&#xff0c;leaf 为true 1 import java.util.*;import 蓝桥杯.dfs_n皇后; public class 特殊日期 {static int sum(int d){int res 0;while(d > 0){res d % 10;d / 10;}return…

基于Springboot+Vue的Java项目-房产销售系统(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

FlexLua低代码便捷打造4G转RS485网关设备

在物联网时代&#xff0c;各种设备之间的互联互通变得越来越重要&#xff0c;而4G转RS485网关设备的出现为不同设备之间的通信提供了更便捷的方式&#xff0c;推动了物联网技术的发展。 4G转RS485网关的通信原理相对简单易懂。它通过4G网络接收数据&#xff0c;然后将数据转换成…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之十三 简单去除图片水印效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之十三 简单去除图片水印效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之十三 简单去除图片水印效果 一、简单介绍 二、简单去除图片水印效果实现原理 三、简单去除图片水印效果案例…

Java入门基础知识第八课(数组)——冒泡排序、Arrays工具类

前面二白讲了关于数组的概念、语法以及简单的输入输出&#xff0c;实际上关于数组的知识还有很多&#xff0c;接下来咱们讲一下冒泡排序以及一些常用的Arrays工具类&#xff0c;需要记忆的知识很多&#xff0c;而且容易混淆。 一、冒泡排序 简介&#xff08;原理&#xff09;…