Antworten:
Eine enge Kopplung liegt vor, wenn eine Gruppe von Klassen stark voneinander abhängig ist.
Dieses Szenario tritt auf, wenn eine Klasse zu viele Aufgaben übernimmt oder wenn ein Anliegen auf mehrere Klassen verteilt ist, anstatt eine eigene Klasse zu haben.
Eine lose Kopplung wird durch ein Design erreicht, das die Einzelverantwortung und die Trennung von Anliegen fördert.
Eine lose gekoppelte Klasse kann unabhängig von anderen (konkreten) Klassen konsumiert und getestet werden.
Schnittstellen sind ein leistungsstarkes Werkzeug zum Entkoppeln. Klassen können über Schnittstellen und nicht über andere konkrete Klassen kommunizieren, und jede Klasse kann sich am anderen Ende dieser Kommunikation befinden, indem sie einfach die Schnittstelle implementiert.
Beispiel für eine dichte Kupplung:
class CustomerRepository
{
private readonly Database database;
public CustomerRepository(Database database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
class Database
{
public void AddRow(string Table, string Value)
{
}
}
Beispiel für lose Kupplung:
class CustomerRepository
{
private readonly IDatabase database;
public CustomerRepository(IDatabase database)
{
this.database = database;
}
public void Add(string CustomerName)
{
database.AddRow("Customer", CustomerName);
}
}
interface IDatabase
{
void AddRow(string Table, string Value);
}
class Database implements IDatabase
{
public void AddRow(string Table, string Value)
{
}
}
Ein weiteres Beispiel hier .
Der Hut ist "lose mit dem Körper verbunden". Dies bedeutet, dass Sie den Hut leicht abnehmen können, ohne Änderungen an der Person / dem Körper vorzunehmen. Wenn Sie das können, haben Sie "lose Kupplung". Siehe unten für die Ausarbeitung.
Denken Sie an Ihre Haut. Es klebt an deinem Körper. Es passt wie angegossen. Aber was ist, wenn Sie Ihre Hautfarbe von Weiß auf Grün ändern möchten? Können Sie sich vorstellen, wie schmerzhaft es wäre, Ihre Haut abzuziehen, zu färben und sie dann wieder aufzutragen usw.? Das Ändern Ihrer Haut ist schwierig, da sie eng mit Ihrem Körper verbunden ist. Sie können einfach keine Änderungen vornehmen. Sie müssten einen Menschen grundlegend neu gestalten, um dies zu ermöglichen.
Gott war kein guter objektorientierter Programmierer.
Denken Sie jetzt daran, sich morgens anzuziehen. Du magst Blau nicht? Keine Probleme: Sie können stattdessen ein rotes Hemd anziehen. Sie können dies einfach und mühelos tun, da das Hemd nicht wie Ihre Haut mit Ihrem Körper verbunden ist. Das Shirt weiß nicht oder kümmert sich nicht darum, welchen Körper es hat . Mit anderen Worten, Sie können Ihre Kleidung wechseln, ohne Ihren Körper wirklich zu verändern.
Das ist das Grundkonzept auf den Punkt gebracht.
Dies ist wichtig, da sich die Software ständig ändert. Im Allgemeinen möchten Sie in der Lage sein, Ihren Code einfach zu ändern, ohne Ihren Code zu ändern. Ich weiß, das klingt wie ein Oxymoron, aber bitte ertrage es mit mir.
CSV / JSON / DB-Beispiele: Wenn jemand seine Ausgabe in einer CSV-Datei anstatt in JSON usw. haben möchte oder wenn Sie von MySQL zu PostGreSQL wechseln möchten, sollten Sie in der Lage sein, diese Änderungen extrem einfach in Ihrem Code vorzunehmen, ohne sie neu schreiben zu müssen die gesamte Klasse usw. Mit anderen Worten, Sie möchten Ihre Anwendung nicht eng mit einer bestimmten Datenbankimplementierung (z. B. MySQL) oder einer bestimmten Ausgabe (z. B. CSV-Dateien) verknüpfen. Denn wie es in der Software unvermeidlich ist, werden sich Änderungen ergeben. Wenn sie kommen, ist es viel einfacher, wenn Ihre Teile Ihres Codes lose miteinander verbunden sind.
Beispiel für Autoteile : Wenn jemand sein Auto in Schwarz haben möchte , sollte man nicht das gesamte Auto neu gestalten müssen, um dies zu tun. Ein Auto und seine Ersatzteile wären ein perfektes Beispiel für eine lose gekoppelte Architektur. Wenn Sie Ihren Motor durch einen besseren ersetzen möchten, sollten Sie in der Lage sein, Ihren Motor ohne großen Aufwand einfach auszubauen und gegen einen besseren auszutauschen. Wenn Ihr Auto nur mit Rolls Royce 1234-Motoren und keinen anderen Motoren funktioniert, ist Ihr Auto eng mit diesem Motor verbunden (Rolls Royce 1234). Es wäre besser, wenn Sie das Design Ihres Autos so ändern würden, dass es mit jedem funktioniertMotor, so dass es etwas lockerer mit seinen Komponenten gekoppelt ist. Noch besser wäre es, wenn Ihr Auto ohne Motor funktionieren könnte! Es wird eine gewisse Kopplung geben, aber Sie sollten daran arbeiten, diese so gering wie möglich zu halten. Warum? Denn wenn sich die Anforderungen ändern, sollten wir immer noch in der Lage sein, sehr schnell qualitativ hochwertige Software zu liefern, und wir werden durch lose Kopplung bei diesem Ziel unterstützt.
Kurz gesagt, eine lose Kopplung erleichtert das Ändern des Codes. Die obigen Antworten enthalten einen Code, der an dieser Stelle lesenswert ist.
Betreff: @ TimoHuovinen kommentiert - das Konzept der losen Kopplung geht Hand in Hand mit den Konzepten des Polymorphismus. Wenn Sie die grundlegende Analogie eines Hemd- / Autoteils verstehen, sind Sie bereit, den Polymorphismus zu verstehen. An dieser Stelle lesen Sie am besten die Codebeispiele, die meine geschätzten Kollegen in den anderen Antworten in diesem Thread bereitgestellt haben. Wenn ich noch mehr sage, werden Sie möglicherweise mit zu vielen Informationen überladen.
Beim objektorientierten Entwurf bezieht sich das Ausmaß der Kopplung darauf, wie stark der Entwurf einer Klasse vom Entwurf einer anderen Klasse abhängt. Mit anderen Worten, wie oft erzwingen Änderungen in Klasse A erzwungene Änderungen in Klasse B? Enge Kopplung bedeutet, dass sich die beiden Klassen häufig zusammen ändern, lose Kopplung bedeutet, dass sie größtenteils unabhängig sind. Im Allgemeinen wird eine lose Kupplung empfohlen, da sie einfacher zu testen und zu warten ist.
Dieses Papier von Martin Fowler (PDF) ist möglicherweise hilfreich.
Im Allgemeinen ist die enge Kopplung in den meisten Fällen schlecht, da sie die Flexibilität und Wiederverwendbarkeit von Code verringert, Änderungen erheblich erschwert, die Testbarkeit beeinträchtigt usw.
Eng gekoppeltes Objekt ist ein Objekt, das einiges über einander wissen muss und normalerweise stark von den Schnittstellen der anderen abhängig ist. Das Ändern eines Objekts in einer eng gekoppelten Anwendung erfordert häufig Änderungen an einer Reihe anderer Objekte. In kleinen Anwendungen können wir die Änderungen leicht identifizieren und es besteht eine geringere Wahrscheinlichkeit, dass etwas übersehen wird. In großen Anwendungen sind diese Abhängigkeiten jedoch nicht immer jedem Programmierer bekannt, oder es besteht die Möglichkeit, dass Änderungen übersehen werden. Aber jeder Satz lose gekoppelter Objekte ist nicht von anderen abhängig.
Kurz gesagt, lose Kopplung ist ein Entwurfsziel, das darauf abzielt, die Abhängigkeiten zwischen Komponenten eines Systems zu verringern, um das Risiko zu verringern, dass Änderungen an einer Komponente Änderungen an einer anderen Komponente erfordern. Die lose Kopplung ist ein viel allgemeineres Konzept, das die Flexibilität eines Systems erhöhen, es wartbarer machen und das gesamte Framework "stabiler" machen soll.
Kopplung bezieht sich auf den Grad des direkten Wissens, den ein Element über ein anderes hat. wir können sagen zB: A und B, nur B ändert sein Verhalten nur, wenn A sein Verhalten ändert. Ein lose gekoppeltes System kann leicht in definierbare Elemente zerlegt werden.
Wenn zwei Objekte lose miteinander verbunden sind, können sie interagieren, kennen sich jedoch nur sehr wenig.
Locker gekoppelte Designs ermöglichen es uns, flexible OO-Systeme zu bauen, die Veränderungen bewältigen können.
Das Beobachter-Entwurfsmuster ist ein gutes Beispiel dafür, wie Klassen lose gekoppelt werden können. Sie können es in Wikipedia nachlesen .
Ein Auszug aus meinem Blogbeitrag zur Kopplung:
Was ist eine enge Kopplung : -
Wie oben definiert, ist ein eng gekoppeltes Objekt ein Objekt, das über andere Objekte Bescheid wissen muss und normalerweise stark von den Schnittstellen des jeweils anderen abhängig ist.
Wenn wir ein Objekt in einer eng gekoppelten Anwendung ändern, müssen häufig Änderungen an einer Reihe anderer Objekte vorgenommen werden. In einer kleinen Anwendung gibt es kein Problem. Wir können die Änderung leicht identifizieren. Bei großen Anwendungen sind diese Abhängigkeiten jedoch nicht immer jedem Verbraucher oder anderen Entwicklern bekannt, oder es besteht eine große Wahrscheinlichkeit für zukünftige Änderungen.
Nehmen wir einen Warenkorb-Demo-Code, um die enge Kopplung zu verstehen:
namespace DNSLooseCoupling
{
public class ShoppingCart
{
public float Price;
public int Quantity;
public float GetRowItemTotal()
{
return Price * Quantity;
}
}
public class ShoppingCartContents
{
public ShoppingCart[] items;
public float GetCartItemsTotal()
{
float cartTotal = 0;
foreach (ShoppingCart item in items)
{
cartTotal += item.GetRowItemTotal();
}
return cartTotal;
}
}
public class Order
{
private ShoppingCartContents cart;
private float salesTax;
public Order(ShoppingCartContents cart, float salesTax)
{
this.cart = cart;
this.salesTax = salesTax;
}
public float OrderTotal()
{
return cart.GetCartItemsTotal() * (2.0f + salesTax);
}
}
}
Probleme mit dem obigen Beispiel
Enge Kopplung schafft einige Schwierigkeiten.
Hier OrderTotal()
geben Methoden uns den vollständigen Betrag für die aktuellen Artikel der Wagen. Wenn wir die Rabattfunktionen in diesem Warenkorbsystem hinzufügen möchten. Im obigen Code ist dies sehr schwierig, da wir in jeder Klasse Änderungen vornehmen müssen, da diese sehr eng miteinander verbunden sind.
Lose Kopplung bedeutet, dass der Grad der Abhängigkeit zwischen zwei Komponenten sehr gering ist.
Beispiel: GSM SIM
Enge Kopplung bedeutet, dass der Grad der Abhängigkeit zwischen zwei Komponenten sehr hoch ist.
Beispiel: CDMA Mobile
So wie ich es verstehe, bietet eine eng gekoppelte Architektur im Vergleich zu einer lose gekoppelten Architektur nicht viel Flexibilität für Änderungen.
Bei lose gekoppelten Architekturen, Nachrichtenformaten oder Betriebsplattformen wirkt sich die Überarbeitung der Geschäftslogik jedoch nicht auf das andere Ende aus. Wenn das System für eine Überarbeitung heruntergefahren wird, kann das andere Ende natürlich eine Weile nicht auf den Dienst zugreifen, aber ansonsten kann das unveränderte Ende den Nachrichtenaustausch wieder aufnehmen, wie es vor der Überarbeitung war.
Enge Kopplung bedeutet, dass eine Klasse von einer anderen Klasse abhängig ist.
Lose Kopplung bedeutet, dass eine Klasse eher von der Schnittstelle als von der Klasse abhängig ist.
Bei der engen Kopplung werden in Methoden fest codierte Abhängigkeiten deklariert.
Bei der losen Kopplung müssen wir die Abhängigkeit zur Laufzeit extern übergeben, anstatt sie fest zu codieren. (Lose Paarsysteme verwenden eine Schnittstelle für eine geringere Abhängigkeit von der Klasse.)
Zum Beispiel haben wir ein System, das Ausgaben auf zwei oder mehr Arten senden kann, wie JSON-Ausgaben, CSV-Ausgaben usw.
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();
}
}
Wenn wir im obigen Beispiel die Ausgabe in JSON ändern möchten, müssen wir den gesamten Code finden und ändern, da Class1 eng mit der CSVOutputGenerator-Klasse gekoppelt ist.
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();
}
}
Es gibt bestimmte Tools, die Abhängigkeitsinjektion über ihre Bibliothek bereitstellen, z. B. in .net haben wir ninject Library .
Wenn Sie in Java weiter gehen, bietet der Frühling diese Funktionen.
Locker gekoppelte Objekte können durch Einfügen von Schnittstellen in Ihren Code erstellt werden. Genau das tun diese Quellen.
Sagen Sie in Ihrem Code, den Sie schreiben
Myclass m = new Myclass();
Diese Aussage in Ihrer Methode besagt, dass Sie davon abhängig sind, myclass
wird als eng gekoppelt bezeichnet. Wenn Sie nun eine Konstruktorinjektion oder eine Eigenschaftsinjektion und ein instanziierendes Objekt bereitstellen, wird es lose gekoppelt.
Es gibt hier viele nette Antworten mit Analogien, aber ein Freund bei der Arbeit gab mir ein Beispiel, das mir mehr gefiel als alle hier genannten ... Augen und Brillen!
Enge Kupplung
Enge Kopplung wären die Augen. Wenn ich mein Sehvermögen verbessern möchte, ist eine Augentransplantation sehr teuer und birgt ein angemessenes Risiko. Aber was wäre, wenn der Designer (als Mensch) einen besseren Weg finden würde? Fügen Sie eine Funktion hinzu, die lose mit dem Körper verbunden ist, damit sie leicht geändert werden kann! (ja .. Brille)
Lose Kopplung
Ich kann meine Brille leicht ersetzen, ohne meine zugrunde liegende Sicht zu beeinträchtigen. Ich kann die Brille abnehmen und meine Sicht wird so sein, wie sie vorher war (nicht besser oder schlechter). Die Verwendung verschiedener Brillen verändert die Sichtweise der Welt durch unsere Augen mit geringem Risiko und einfacher Wartbarkeit.
Zusammenfassung
Wenn Sie das nächste Mal gefragt werden, wen interessiert es, ob mein Code eng gekoppelt ist? Die Antwort dreht sich alles um Veränderungsbemühungen, Wartungsbemühungen und das Risiko von Veränderungen.
Wie geht das in C #? Schnittstellen und Abhängigkeitsinjektion!
BEARBEITEN
Dies ist auch ein gutes Beispiel für das Dekorationsmuster, bei dem die Augen die Klasse sind, die wir dekorieren, indem wir die Anforderungen der Benutzeroberfläche erfüllen, aber unterschiedliche Funktionen bieten (z. B. Sonnenbrillen, Lesebrillen, Lupen für Juweliere usw.).
Lose Kopplung ist eine Antwort auf fest codierte Abhängigkeiten alten Stils und verwandte Probleme wie häufiges Neukompilieren, wenn sich etwas ändert, und Wiederverwendung von Code. Es wird Wert darauf gelegt, die Worker-Logik in Komponenten zu implementieren und dort lösungsspezifischen Verkabelungscode zu vermeiden.
Lose Kopplung = IoC Siehe dies für eine einfachere Erklärung.
Lose Kopplung ist der Prozess, bei dem die Abhängigkeit, die Ihre Klasse benötigt, indirekt angegeben wird, ohne alle Informationen der Abhängigkeit (dh in der From-Schnittstelle) anzugeben, falls Sie eine enge Kopplung direkt in der Abhängigkeit angeben, die keine gute Codierungsmethode darstellt.
Es geht um Klassen Abhängigkeitsrate auf einen anderen diejenigen , die so niedrig ist , in lose gekoppelt und so hoch , in eng gekoppelt. Um in der Dienstorientierungsarchitektur klar zu sein , sind Dienste lose miteinander gegen monolithisch gekoppelt, wobei die Klassenabhängigkeit absichtlich voneinander abhängt
Wenn die Entstehung / Existenz eines Objekts von einem anderen Objekt abhängt, das nicht angepasst werden kann, ist seine enge Kopplung. Und wenn die Abhängigkeit angepasst werden kann, ist ihre lose Kopplung. Betrachten Sie ein Beispiel in Java:
class Car {
private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
// Other parts
public Car() {
// implemenation
}
}
Der Client der Car
Klasse kann eine mit NUR der "X_COMPANY" -Engine erstellen.
Ziehen Sie in Betracht, diese Kopplung zu brechen, um Folgendes zu ändern:
class Car {
private Engine engine;
// Other members
public Car( Engine engine ) { // this car can be created with any Engine type
this.engine = engine;
}
}
Jetzt ist a Car
nicht von einer Engine von "X_COMPANY" abhängig, da sie mit Typen erstellt werden kann.
Ein Java-spezifischer Hinweis: Die Verwendung von Java-Schnittstellen nur zum Entkoppeln ist kein geeigneter Entwurfsansatz. In Java hat eine Schnittstelle den Zweck, als Vertrag zu fungieren, der das Verhalten / den Vorteil der Entkopplung auf intrinsische Weise bietet.
Der Kommentar von Bill Rosmus in der akzeptierten Antwort hat eine gute Erklärung.
Enge Kopplung bedeutet, dass Klassen und Objekte voneinander abhängig sind. Im Allgemeinen ist eine enge Kopplung normalerweise nicht gut, da sie die Flexibilität und Wiederverwendbarkeit des Codes verringert, während eine lose Kopplung bedeutet, die Abhängigkeiten einer Klasse zu verringern, die die verschiedenen Klassen direkt verwendet.
Enge Kopplung Das eng gekoppelte Objekt ist ein Objekt, das über andere Objekte Bescheid wissen muss und normalerweise stark von den Schnittstellen des jeweils anderen abhängig ist. Das Ändern eines Objekts in einer eng gekoppelten Anwendung erfordert häufig Änderungen an einer Reihe anderer Objekte. In den kleinen Anwendungen können wir die Änderungen leicht identifizieren und es besteht eine geringere Wahrscheinlichkeit, dass etwas übersehen wird. In großen Anwendungen sind diese Abhängigkeiten jedoch nicht immer jedem Programmierer bekannt, und es besteht die Möglichkeit, Änderungen zu übersehen. Beispiel:
class A {
public int a = 0;
public int getA() {
System.out.println("getA() method");
return a;
}
public void setA(int aa) {
if(!(aa > 10))
a = aa;
}
}
public class B {
public static void main(String[] args) {
A aObject = new A();
aObject.a = 100; // Not suppose to happen as defined by class A, this causes tight coupling.
System.out.println("aObject.a value is: " + aObject.a);
}
}
In the above example, the code that is defined by this kind of implementation uses tight coupling and is very bad since class B knows about the detail of class A, if class A changes the variable 'a' to private then class B breaks, also class A's implementation states that variable 'a' should not be more than 10 but as we can see there is no way to enforce such a rule as we can go directly to the variable and change its state to whatever value we decide.
Output
aObject.a value is: 100
Loose Coupling
Loose coupling is a design goal to reduce the inter-dependencies between components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
Loose coupling is a much more generic concept intended to increase the flexibility of the system, make it more maintainable and makes the entire framework more stable.
Example:
class A {
private int a = 0;
public int getA() {
System.out.println("getA() method");
return a;
}
public void setA(int aa) {
if(!(aa > 10))
a = aa;
}
}
public class B {
public static void main(String[] args) {
A aObject = new A();
aObject.setA(100); // No way to set 'a' to such value as this method call will
// fail due to its enforced rule.
System.out.println("aObject value is: " + aObject.getA());
}
}
Im obigen Beispiel verwendet der Code, der durch diese Art der Implementierung definiert wird, eine lose Kopplung und wird empfohlen, da Klasse B Klasse A durchlaufen muss, um den Status zu erhalten, in dem Regeln durchgesetzt werden. Wenn Klasse A intern geändert wird, wird Klasse B nicht unterbrochen, da nur Klasse A als Kommunikationsmittel verwendet wird.
Output
getA() method
aObject value is: 0