高内聚低耦合法则实例解析

定义:一个对象应该对其他对象保持最少的了解。

问题由来:类与类之间的关系越来越密切,耦合度越来越大,当一个类发生改变时,对另外一个类的影响也越大.

解决方案:尽量降低类与类之间的耦合.

自从我们接触到编程开始,就知道了软件设计的总的原则,低耦合,高内聚,无论是面向对象或者面向过程,耦合度尽量低,才能提高代码的复用率。但是编程怎么编程低耦合呢?

无论逻辑怎么复杂,对于依赖的类来说,都尽量将逻辑封装在类的内部,对外除了提供的public方法,不对外泄露任何信息。还有一个更加简单的定义:只与直接的朋友通信。首先解释一下什么是直接的朋友;每个对象都会与其他对象发生耦合关系,我们就说这两个对象之间有耦合关系,我们就说这两个对象有朋友关系,耦合发生的方式有很多,依赖,关联,组合,聚合等等。其中,我们称出现成员变量,方法参数,方法返回值的类称为直接的朋友,而出现在局部变量中的类为不是直接的朋友,也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部;

举一个例子,在一所学校,里面有老师若干名,依次编号。下面有学生若干名,一次编号。现在要求打印出所有的老师和学生的ID.

先来违反低耦合高内聚原则

代码如下。

package test1;
import java.util.ArrayList;
import java.util.List;
class Teacher{
	privateString id;
	publicvoidsetId(String id)
	 {
		this.id=id;
	}
	publicString getId()
	 {
		return id;
	}
}
class Student{
	private String id;
	public void setId(String id)
	 {
		this.id=id;
	}
	public String getId()
	 {
		return id;
	}
}
class StudentManage{
	publicList<Student> getAllStudent()
	 {
		List<Student> list=newArrayList<Student>();
		for (int i=0;i<100;i++)
		  {
			Student student=new Student();
			student.setId("学生学号是"+i);
			list.add(student);
		}
		return list;
	}
}
class TeacherManage
{
	publicList<Teacher> getAllTeacher()
	 {
		List<Teacher> list=newArrayList<Teacher>();
		for (inti=0;i<100;i++)
		 {
			Teacher teacher =new Teacher();
			teacher.setId("老师编号"+i);
			list.add(teacher);
		}
		return list;
	}
	public void printAllPerson(StudentManagestudentmanager)
	 {
		List<Student>list1=studentmanager.getAllStudent();
		for (Student s:list1)
		  {
			System.out.println(s.getId());
		}
		List<Teacher>list2=this.getAllTeacher();
		for (Teacher t:list2)
		  {
			System.out.println(t.getId());
		}
	}
}
public classClient {
	publicstaticvoidmain(String[] args) {
		TeacherManagetm=newTeacherManage();
		tm.printAllPerson(new StudentManage());
	}
}

现在这个设计的主要问题出现在TeacherManage类中,根据低耦合高内聚法则,只与直接的朋友进行通信,而Student类并不是TeacherManage类中的直接朋友,应避免类中出现这样非直接朋友关系的耦合。

修改之后代码如下:

package test2;
import java.util.ArrayList;
import java.util.List;
class Teacher{
	privateString id;
	publicvoidsetId(String id)
	 {
		this.id=id;
	}
	publicString getId()
	 {
		return id;
	}
}
class Student{
	private String id;
	public void setId(String id)
	 {
		this.id=id;
	}
	public String getId()
	 {
		return id;
	}
}
class StudentManage{
	publicList<Student> getAllStudent()
	 {
		List<Student> list=newArrayList<Student>();
		for (int i=0;i<100;i++)
		  {
			Student student=new Student();
			student.setId("学生学号是"+i);
			list.add(student);
		}
		return list;
	}
	public void printAllStudent()
	 {
		List<Student>list1=this.getAllStudent();
		for (Student s:list1)
		  {
			System.out.println(s.getId());
		}
	}
}
class TeacherManage
{
	publicList<Teacher> getAllTeacher()
	 {
		List<Teacher> list=newArrayList<Teacher>();
		for (inti=0;i<100;i++)
		 {
			Teacher teacher =new Teacher();
			teacher.setId("老师编号"+i);
			list.add(teacher);
		}
		return list;
	}
	publicvoidprintAllTeacher()
	 {
		List<Teacher> list2=this.getAllTeacher();
		for (Teacher t:list2)
		  {
			System.out.println(t.getId());
		}
	}
}
public classClient {
	publicstaticvoidmain(String[] args) {
		TeacherManagetm=newTeacherManage();
		tm.printAllTeacher();
		StudentManagesm=newStudentManage();
		sm.printAllStudent();
	}
}

修改后,学生新增加了学生ID的方法,老师直接来调用即可。从而避免了与学生发生耦合。低耦合高内聚原则的初衷是降低了类之间的耦合,由于每个类减少了不必要的依赖,因此的确可以降低耦合关系,但是凡事有个度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生关系。采用此法则可以做到结构清晰,高内聚低耦合、

耦合性与内聚性是模块独立性的两个定性标准,将软件系统划分模块时,尽量做到高内聚低耦合,提高模块的独立性,为设计高质量的软件结构奠定基础。

有个例子很容易明白:一个程序有50个函数,这个程序执行得非常好;然而一旦你修改其中一个函数,其他49个函数都需要做修改,这就是高耦合的后果。

总结

以上就是本文关于高内聚低耦合法则实例代码解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • Java依赖倒转原则_动力节点Java学院整理

    定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒置原则基于这样一个事实:相对于细节的多变性,

  • 浅谈java中OO的概念和设计原则(必看)

    一.OO(面向对象)的设计基础 面向对象(OO):就是基于对象概念,以对象为中心,以类和继承为构造机制,充分利用接口和多态提供灵活性,来认识.理解.刻划客观世界和设计.构建相应的软件系统.面向对象的特征:虽然各种面向对象编程语言相互有别,但都能看到它们对面向对象基本特征的支持, 即 "抽象.封装.继承.多态" : – 抽象,先不考虑细节 – 封装,隐藏内部实现 – 继承,复用现有代码 – 多态,改写对象行为 面向对象设计模式:是"好的面向对象设计",所谓"

  • 里氏代换原则_动力节点Java学院整理

    聊一聊里氏代换原则. 定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型. 定义2:所有引用基类的地方必须能透明地使用其子类的对象. 问题由来:有一功能P1,由类A完成.现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成.新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能

  • 开放封闭原则_动力节点Java学院整理

    定义:软件实体(类.模块.函数等)应该是可以扩展的,但是不可修改.对于扩展是开放的,对于更改是封闭的.关键是抽象,将一个功能的通用部分和实现细节部分清晰的分离开来. 这里要求我们写代码要有抽象的概念.什么是抽象?指由实体抽离出概念的思考过程.就是从众多的对象中抽离出共同的本质的特征.在写代码的过程中,需要抽象类的地方,只需要抓住这个类的本质功能,不要老想着它在这个工程中的具体功能. 我们继续看开放封闭原则,这个原则要求,将一个功能的共用部分和实现部分清晰地分离开来.因为在最初搭建架构的时候你不能

  • 合成聚合复用原则_动力节点Java学院整理

    合成聚合复用原则 合成复用原则又称为组合/聚合复用原则(Composition/Aggregate Reuse Principle, CARP),其定义如下: 合成复用原则(Composite Reuse Principle, CRP):尽量使用对象组合,而不是继承来达到复用的目的. 合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分:新对象通过委派调用已有对象的方法达到复用功能的目的.简言之:复用时要尽量使用组合/聚合关系(关联关

  • 高内聚低耦合原则_动力节点Java学院整理

    一.什么是耦合度 软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准.划分摸块的一个准则就是高内聚低耦合. 耦合度(Coupling)是对模块间关联程度的度量.耦合的强弱取决与模块间接口的复杂性.调用模块的方式以及通过界面传送数据的多少. 模块间的耦合度是指模块之间的依赖关系,包括控制关系.调用关系.数据传递关系.模块间联系越多,其耦合性越强,同时表明其独立性越差.降低模块间的耦合度能减少模块间的影响,防止对某一模块修改所引起的"牵一发动全身"的水波效应,保证系统设计顺利进行.

  • 单一职责原则_动力节点Java学院整理

    定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障. 解决方案:遵循单一职责原则.分别建立两个类T1.T2,使T1完成职责P1功能,T2完成职责P2功能.这样,当修改类T1时,不会使职责P2发生故障风险:同理,当修改T2时,也不会使职责P1发生故障风险. 说到单一职责原则,很多人都会不屑一顾.因为它太简单了.稍有经验的程序员即使

  • 接口隔离原则_动力节点Java学院整理

    定义:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法. 解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系.也就是采用接口隔离原则. 举例来说明接口隔离原则: (图1  未遵循接口隔离原则的设计) 这个图的意思是:类A依赖接口I中的方法1.方法2.方法3,类B是对类A依赖的实现.类C依赖接

  • 高内聚低耦合法则实例解析

    定义:一个对象应该对其他对象保持最少的了解. 问题由来:类与类之间的关系越来越密切,耦合度越来越大,当一个类发生改变时,对另外一个类的影响也越大. 解决方案:尽量降低类与类之间的耦合. 自从我们接触到编程开始,就知道了软件设计的总的原则,低耦合,高内聚,无论是面向对象或者面向过程,耦合度尽量低,才能提高代码的复用率.但是编程怎么编程低耦合呢? 无论逻辑怎么复杂,对于依赖的类来说,都尽量将逻辑封装在类的内部,对外除了提供的public方法,不对外泄露任何信息.还有一个更加简单的定义:只与直接的朋友

  • Redis处理高并发机制原理及实例解析

    1.Redis是基于内存的,内存的读写速度非常快: 2.Redis是单线程的,省去了很多上下文切换线程的时间: 3.Redis使用多路复用技术,可以处理并发的连接.非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架.epoll中的读.写.关闭.连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间. 下面重点介绍单线程设计和IO多路复用核心设计快的原因 为什么Redis是单线程的 1.官方答案 因为Redis是基于内存的操作,CPU不是Redi

  • 使用C语言实例描述程序中的内聚和耦合问题

    编程时,我们讲究的是高内聚低耦合,在协同开发.代码移植.维护等环节都起到很重要的作用. 一.原理篇 而低耦合,是指模块之间尽可能的使其独立存在,模块之间不产生联系不可能,但模块与模块之间的接口应该尽量少而简单.这样,高内聚从整个程序中每一个模块的内部特征角度,低耦合从程序中各个模块之间的关联关系角度,对我们的设计提出了要求. 程序设计和软件工程发展过程中产生的很多技术.设计原则,都可以从内聚和耦合的角度进行解读.作为C语言程序设计的初学者,结合当前对于函数的理解可达到的程度,我们探讨一下如何做到

  • C++命名空间5种常见用法实例解析

    相信小伙伴们对C++已经非常熟悉,但是对命名空间经常使用到的地方还不是很明白,这篇文章就针对命名空间这一块做了一个叙述. 命名空间在1995年被引入到 c++ 标准中,通常是这样定义的: 命名空间定义了新的作用域.它们提供了一种避免名称冲突的方法. c++ 中的命名空间通常用于避免命名冲突.尽管命名空间在最近的 c++ 代码中广泛使用,但大多数较旧代码都不使用此工具. 基于对众多C++项目源码的探索与研究,总结出了在这些项目中使用命名空间的一些常见原因. 1-避免名称冲突 如前所述,这是在C++

  • java线程的基础实例解析

    java中建立线程可以有两种方式,分别是继承Thread类和实现Runnable接口. 继承Thread public class MyThread extends Thread{ public MyThread(String name){ super(name); } int i; public void run(){ for(i=0;i<5;i++){ System.out.println(getName()+"--"+i); } } public static void m

  • Python多线程threading和multiprocessing模块实例解析

    本文研究的主要是Python多线程threading和multiprocessing模块的相关内容,具体介绍如下. 线程是一个进程的实体,是由表示程序运行状态的寄存器(如程序计数器.栈指针)以及堆栈组成,它是比进程更小的单位. 线程是程序中的一个执行流.一个执行流是由CPU运行程序代码并操作程序的数据所形成的.因此,线程被认为是以CPU为主体的行为. 线程不包含进程地址空间中的代码和数据,线程是计算过程在某一时刻的状态.所以,系统在产生一个线程或各个线程之间切换时,负担要比进程小得多. 线程是一

  • Java编码摘要算法实例解析

    这篇文章主要介绍了Java编码摘要算法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 URL 编码与解码 String s = "你好,世界!"; // URL 编码 String urlEncodedString = URLEncoder.encode(s, "UTF-8"); // URL 解码 String urlDecodedString = URLDecoder.decode(urlEncoded

  • React源码state计算流程和优先级实例解析

    目录 setState执行之后会发生什么 根据组件实例获取其 Fiber 节点 创建update对象 将Update对象关联到Fiber节点的updateQueue属性 发起调度 processUpdateQueue做了什么 变量解释 构造本轮更新的 updateQueue 更新 workInProgress 节点 总结 update对象丢失问题 为什么会丢失 如何解决 state计算的连续性 问题现象 如何解决 setState执行之后会发生什么 setState 执行之后,会执行一个叫 en

  • Vuejs第六篇之Vuejs与form元素实例解析

    本文是小编结合官方文档整理的一篇细致代码更多更全的详细教程,非常适合新手学习,感兴趣的朋友一起看看吧! 资料来于官方文档: http://cn.vuejs.org/guide/forms.html 表单绑定 ①常见绑定方法: [1]文本输入框绑定: [2]textarea绑定(类似[1]): [3]radio选中值绑定: [4]checkbox绑定(自动捆绑数组,无需name): [5]select绑定: [6]select multiple多选选中框绑定: [7]动态绑定(以上不同类型但同一个

随机推荐