在面向对象范式中,有人能准确地描述松耦合和紧耦合之间的区别吗?
当前回答
紧密耦合意味着一个类依赖于另一个类。 松耦合意味着一个类依赖于接口而不是类。
在紧密耦合中,方法中声明了硬编码的依赖项。 在松耦合中,我们必须在运行时向外部传递依赖项,而不是硬编码。(松散耦合系统使用接口来减少与类的依赖。)
例如,我们有一个系统可以以两种或多种方式发送输出,如JSON输出、CSV输出等。
紧耦合的
public interface OutputGenerator {
public void generateOutput();
}
public class CSVOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("CSV Output Generator");
}
}
public class JSONOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("JSON Output Generator");
}
}
// In Other Code, we write Output Generator like...
public class Class1 {
public void generateOutput() {
// Here Output will be in CSV-Format, because of hard-coded code.
// This method tightly coupled with CSVOutputGenerator class, if we want another Output, we must change this method.
// Any method, that calls Class1's generateOutput will return CSVOutput, because Class1 is tight couple with CSVOutputGenerator.
OutputGenerator outputGenerator = new CSVOutputGenerator();
output.generateOutput();
}
}
在上面的例子中,如果我们想要更改JSON中的输出,那么我们需要在整个代码中找到并更改,因为Class1与CSVOutputGenerator类紧密耦合。
松散耦合
public interface OutputGenerator {
public void generateOutput();
}
public class CSVOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("CSV Output Generator");
}
}
public class JSONOutputGenerator implements OutputGenerator {
public void generateOutput() {
System.out.println("JSON Output Generator");
}
}
// In Other Code, we write Output Generator like...
public class Class1 {
public void generateOutput(OutputGenerator outputGenerator) {
// if you want to write JSON, pass object of JSONOutputGenerator (Dependency will be passed externally to this method)
// if you want to write CSV, pass object of CSVOutputGenerator (Dependency will be passed externally to this method)
// Due to loose couple with class, we don't need to change code of Class1, because Class1 is loose coupled with CSVOutputGenerator or JSONOutputGenerator class
// Any method, that calls Class1's generateOutput will desired output, because Class1 does not tight couple with CSVOutputGenerator or JSONOutputGenerator class
OutputGenerator outputGenerator = outputGenerator;
output.generateOutput();
}
}
其他回答
在面向对象设计中,耦合量指的是一个类的设计依赖于另一个类的设计的程度。换句话说,A类力的变化与B类力的变化相关的频率是多少?紧耦合意味着两个类经常一起更改,松耦合意味着它们大部分是独立的。一般来说,推荐使用松耦合,因为它更容易测试和维护。
你可能会发现Martin Fowler的这篇论文(PDF)很有帮助。
松耦合和紧耦合是关于程序组件之间的依赖关系。这意味着不仅依赖于编程类,还依赖于编程系统组件。
例如,如果你只使用简单的原始SQL查询从SQL Server接收数据,这是松耦合。与松耦合和简单原始SQL查询相反的是紧耦合和实体框架核心。在实体框架核心,你必须完整的模型与POCO类在你的代码反映数据库结构,这意味着任何变化在数据库中,你必须反映在代码。
因此,程序代码和数据库结构之间的紧密耦合是实体框架,这种方法的对立面是拒绝使用任何ORM,并拒绝在程序代码中使用完整的镜像数据库结构。
这是关于类对其他类的依赖率,在松散耦合时很低,而在紧密耦合时很高。在面向服务的体系结构中,服务之间是松散耦合的,不同的类之间的依赖是有意的
无代码说明
用简单的类比来解释概念。代码可以稍后再写。
松耦合的例子:
在上图中,帽子与身体“松散耦合”。这意味着你可以很容易地摘下帽子,而不需要对人/身体做任何改变。当你能做到这一点时,你就有了“松耦合”。详情见下文。
详细的例子
想想你的皮肤。它粘在你身上了。它非常合适。但是如果你想把你的肤色从白色变成黑色呢?你能想象剥掉你的皮肤,染色,然后再贴回去有多痛苦吗?改变你的皮肤是困难的,因为它与你的身体紧密相连。你只是不能轻易做出改变。为了使这成为可能,你必须从根本上重新设计一个人。
关键点#1:换句话说,如果你想改变皮肤,你也必须改变你身体的设计,因为两者是连接在一起的——它们是紧密耦合的。
上帝不是一个优秀的面向对象程序员。
松耦合(详细示例)
现在想想早上穿衣服。你不喜欢蓝色?没问题:你可以换一件红衬衫。你可以轻松轻松地做到这一点,因为衬衫并不像皮肤那样真正地连接在你的身体上。衬衫不知道也不关心它穿在什么身体上。换句话说,你可以改变你的衣服,而不需要真正改变你的身体。
这是第二点。如果你换了衬衫,那么你就不会被迫改变你的身体——当你可以这样做时,你就有了松耦合。当你不能这样做时,你就有了紧密耦合。
这是一个简单的基本概念。
为什么所有这些都很重要?
在编写软件时,更改是不可避免的。如果我们提前知道变更将发生在某个特定的地方,那么我们应该确保我们的软件在那个特定的点上是松散耦合的,因为这将使我们能够轻松快速地进行这些更改,而没有错误.....这意味着什么呢?看一些例子:
软件中的松耦合:
CSV/JSON示例:在我职业生涯的早期,我的经理说:“给我一个CSV文件的输出”。太好了。我开始努力,创造了一个像魔法一样有效的日常工作。一两周后,他说:“实际上,我想为另一个客户端提供JSON格式的输出。”
真痛苦。我不得不重写整个剧本。我有点知道会发生这种情况,所以我用接口重写了整个程序——一种松散耦合的设计模式,现在,添加了新的输出格式,进行更改就容易多了。我可以编辑JSON部分,而不用担心我会破坏我的CSV输出。
另外重要的一点是:软件的变化是正常的。在变化点上松散耦合。
DB Examples: if you want to switch from sqlLite to PostGreSQL easily - loosely coupled code makes it really easy to switch (i.e. to put on a red shirt instead of a blue shirt). The Rails ActiveRecord library is loosely coupled on its database implementation. This makes it super easy for someone to use their own database implementation, while using the same code base! Cloud Provider examples: Or if you're using AWS and they start charging too much because of market dominance, you should be able to somewhat easily switch to Google or Azure etc. This is precisely the reason why libraries like Active Storage exist - they provide users with a healthy indifference as to the specific cloud provider being used (Azure, AWS S3, GCS etc.). You can easily change cloud providers with just a one-line code change. The implementation details of the cloud storage providers are loosely coupled. Testing: if you want to test your software, with predetermined outputs and inputs - how are you going to do it? With loosely coupled software - it's a breeze: you can run your tests, and you can also deploy your production code and do it all in the same code base. With tightly coupled code, testing your production code is nearly impossible.
我们是否需要让所有内容都“松散耦合”?可能不会。我们必须运用我们的判断力。一定程度的耦合是不可避免的。但是如果你提前知道它会在哪里发生变化,就考虑最小化它。我还建议不要猜测事情会在哪里发生变化,不要将所有事情松散耦合。松散的情侣,只在你需要的时候。
总结
简而言之,松耦合使代码更容易更改。
上面的答案提供了一些值得一读的代码。
高级的主题
松耦合与多态性和接口密切相关。如果你喜欢漫画和类比,看看我写过的其他文章:
什么是多态性? 什么是接口? 你说的“漏洞百出的抽象”是什么意思——不是我写的。
归因。
有一些工具通过它们的库提供依赖注入,例如在。net中我们有ninject库。
如果在java中更进一步,那么spring提供了这种功能。
松散耦合的对象可以通过在代码中引入接口来实现,这就是这些源代码所做的。
在你正在编写的代码中
Myclass m = new Myclass();
现在你的方法中的这个语句说你依赖于myclass这被称为紧耦合。现在你提供了一些构造函数注入,或者属性注入实例化对象,然后它就会变得松散耦合。
推荐文章
- 如何在方法中访问“静态”类变量?
- 使arrayList.toArray()返回更具体的类型
- 如何从对象数组中通过对象属性找到条目?
- 为什么c#不提供c++风格的'friend'关键字?
- new Object()和对象文字表示法的区别是什么?
- String, StringBuffer和StringBuilder
- JavaScript对象如何引用自身的值?
- 在c#中创建一个对象的副本
- PHP检查对象或类中是否存在属性
- 存储库和服务层的区别?
- DDD -实体不能直接访问存储库的规则
- 为什么STL如此严重地基于模板而不是继承?
- 如何在Objective-C中声明类级属性?
- 面向方面编程与面向对象编程
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象