在面向对象范式中,有人能准确地描述松耦合和紧耦合之间的区别吗?
当前回答
松耦合是在不提供依赖关系的所有信息的情况下,间接地给出类所需要的依赖关系的过程。E在from的接口中),以防紧耦合,你直接给出依赖关系,这不是编码的好方法。
其他回答
这是关于类对其他类的依赖率,在松散耦合时很低,而在紧密耦合时很高。在面向服务的体系结构中,服务之间是松散耦合的,不同的类之间的依赖是有意的
无代码说明
用简单的类比来解释概念。代码可以稍后再写。
松耦合的例子:
在上图中,帽子与身体“松散耦合”。这意味着你可以很容易地摘下帽子,而不需要对人/身体做任何改变。当你能做到这一点时,你就有了“松耦合”。详情见下文。
详细的例子
想想你的皮肤。它粘在你身上了。它非常合适。但是如果你想把你的肤色从白色变成黑色呢?你能想象剥掉你的皮肤,染色,然后再贴回去有多痛苦吗?改变你的皮肤是困难的,因为它与你的身体紧密相连。你只是不能轻易做出改变。为了使这成为可能,你必须从根本上重新设计一个人。
关键点#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.
我们是否需要让所有内容都“松散耦合”?可能不会。我们必须运用我们的判断力。一定程度的耦合是不可避免的。但是如果你提前知道它会在哪里发生变化,就考虑最小化它。我还建议不要猜测事情会在哪里发生变化,不要将所有事情松散耦合。松散的情侣,只在你需要的时候。
总结
简而言之,松耦合使代码更容易更改。
上面的答案提供了一些值得一读的代码。
高级的主题
松耦合与多态性和接口密切相关。如果你喜欢漫画和类比,看看我写过的其他文章:
什么是多态性? 什么是接口? 你说的“漏洞百出的抽象”是什么意思——不是我写的。
归因。
一般来说,紧密耦合是不好的,但大多数时候,因为它降低了代码的灵活性和可重用性,它使更改更加困难,它阻碍了可测试性等。
Tightly Coupled Object is an object need to know quite a bit about each other and are usually highly dependent on each other interfaces. Changing one object in a tightly coupled application often requires changes to a number of other objects, In small application we can easily identify the changes and there is less chance to miss anything. But in large applications these inter-dependencies are not always known by every programmer or chance is there to miss changes. But each set of loosely coupled objects are not dependent on others.
简而言之,我们可以说,松耦合是一种设计目标,它寻求减少系统组件之间的相互依赖关系,目的是降低一个组件的更改将要求任何其他组件进行更改的风险。松散耦合是一个更通用的概念,旨在增加系统的灵活性,使其更可维护,并使整个框架更“稳定”。
耦合指的是一个元素对另一个元素的直接认识程度。我们可以说A和B,只有B在A改变其行为时才改变其行为。松散耦合的系统可以很容易地分解为可定义的元素。
有一些工具通过它们的库提供依赖注入,例如在。net中我们有ninject库。
如果在java中更进一步,那么spring提供了这种功能。
松散耦合的对象可以通过在代码中引入接口来实现,这就是这些源代码所做的。
在你正在编写的代码中
Myclass m = new Myclass();
现在你的方法中的这个语句说你依赖于myclass这被称为紧耦合。现在你提供了一些构造函数注入,或者属性注入实例化对象,然后它就会变得松散耦合。
这里有很多使用类比的很好的答案,但是一个工作中的朋友给了我一个例子,比这里提到的所有例子都更让我喜欢……眼睛和眼镜!
紧密耦合
紧密耦合是眼睛。如果我想修复我的视力,做眼部移植手术非常昂贵,而且有相当大的风险。但如果设计师(作为人类)找到了更好的方法呢?添加一个与主体松散耦合的特性,这样就可以轻松地更改它!(是的. .眼镜)
松散耦合
我可以很容易地更换我的眼镜,而不会破坏我的潜在视力。我可以摘下眼镜,我的视力就会恢复到以前的水平(不是更好或更差)。使用不同的眼镜改变了我们通过眼睛看世界的方式,而且风险很小,易于维护。
总结
所以下次有人问你“谁在乎我的代码是否紧密耦合?”答案都是关于努力改变,努力维持和改变的风险。
那么这在c#中是如何实现的呢?接口和依赖注入!
EDIT
这也是Decorator模式的一个很好的例子,其中眼睛是我们通过满足界面需求来装饰的类,但提供了不同的功能(例如太阳镜、老花镜、珠宝商的放大镜等)。
推荐文章
- 如何在方法中访问“静态”类变量?
- 使arrayList.toArray()返回更具体的类型
- 如何从对象数组中通过对象属性找到条目?
- 为什么c#不提供c++风格的'friend'关键字?
- new Object()和对象文字表示法的区别是什么?
- String, StringBuffer和StringBuilder
- JavaScript对象如何引用自身的值?
- 在c#中创建一个对象的副本
- PHP检查对象或类中是否存在属性
- 存储库和服务层的区别?
- DDD -实体不能直接访问存储库的规则
- 为什么STL如此严重地基于模板而不是继承?
- 如何在Objective-C中声明类级属性?
- 面向方面编程与面向对象编程
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象