Ścisłe sprzężenie ma miejsce, gdy grupa klas jest od siebie wysoce zależna.
Ten scenariusz powstaje, gdy klasa przyjmuje zbyt wiele obowiązków lub gdy jedna troska jest rozłożona na wiele klas, zamiast mieć własną klasę.
Luźne sprzężenie osiąga się za pomocą konstrukcji, która promuje pojedynczą odpowiedzialność i rozdzielenie problemów.
Luźno sprzężoną klasę można konsumować i testować niezależnie od innych (konkretnych) klas.
Interfejsy to potężne narzędzie do oddzielania. Klasy mogą komunikować się za pośrednictwem interfejsów, a nie innych konkretnych klas, a każda klasa może znajdować się na drugim końcu tej komunikacji, po prostu implementując interfejs.
Przykład ciasnego połączenia:
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)
{
}
}
Przykład luźnego sprzężenia:
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)
{
}
}
Jak dotąd to, co powiedziałeś, ma sens. Czy możesz wyjaśnić, w jaki sposób mechanizm sprzęgający może odnosić się do wzorca obserwatora?
Jim
1
Wzór obserwatora opisano tutaj: en.wikipedia.org/wiki/Observer_pattern . Ponieważ klasa podmiotu może utrzymywać listę klas dziedziczących po „obserwatorze”, bez faktycznego poznania konkretnego typu tych klas, jest to przypadek luźnego sprzężenia. Temat nie zależy od żadnego z jego obserwatorów ani od ich wewnętrznych obaw. Obserwatorzy nie zależą od przedmiotu ani żadnych jego obaw.
Jonathan
4
Interfejsy Java to narzędzia, które mogą w tym pomóc. Nie są one jednak wymagane. Pojęcie programu do interfejsu, a nie implementacja, oznacza program do publicznych metod / atrybutów (lub tych, które mają być używane przez zewnętrznych wywołujących, gdy języki nie obsługują modyfikatorów dostępu, takich jak C). Interfejs ma honorować ten dorozumiany kontrakt, nie zmieniając go. W językach bez modyfikatorów dostępu (takich jak C) oznacza to tylko używanie opublikowanych interfejsów / funkcji i nie uderzanie w te, które mają być używane wewnętrznie, ponieważ mogą one ulec zmianie w razie potrzeby w celu obsługi opublikowanych funkcji.
Bill Rosmus
3
@jonathanconway dziękuję panu, ale oba fragmenty kodu robią to samo: jaka zatem jest różnica między nimi? tzn. jakie są zalety luźnego łączenia?
BKSpurgeon
1
Widziałem (zasadniczo) ten przykład wcześniej. Moim zdaniem nie miałoby to znaczenia, gdyby istniało wiele rodzajów baz danych. Jeśli planujesz mieć tylko jeden, to czy tak źle jest korzystać z implementacji bezpośrednio, a później, jeśli będziesz musiał wstrzyknąć różne typy, a następnie ponownie zastosuj bazę danych, aby użyć interfejsu? Zamiast dodawać obciążenia kodu płyty kotła, które prawdopodobnie nie są potrzebne?
Carlos Bribiescas
177
Objaśnienie bez ŻADNEGO kodu
Przykład podsumowania:
Kapelusz jest „luźno połączony” z ciałem. Oznacza to, że możesz łatwo zdjąć czapkę bez wprowadzania zmian w osobie / ciele. Kiedy możesz to zrobić, masz „luźne połączenie”. Zobacz poniżej opracowanie.
Szczelne połączenie (szczegółowy przykład)
Pomyśl o swojej skórze. Przylega do twojego ciała. Pasuje jak rękawiczka. Ale co, jeśli chcesz zmienić kolor skóry z białego na zielony? Czy potrafisz sobie wyobrazić, jak bolesne byłoby złuszczanie skóry, farbowanie, a następnie wklejanie z powrotem itp.? Zmiana skóry jest trudna, ponieważ jest ściśle związana z ciałem. Po prostu nie możesz łatwo wprowadzać zmian. Trzeba by zasadniczo przeprojektować człowieka, aby było to możliwe.
Kluczowy punkt # 1 : Innymi słowy, jeśli chcesz zmienić skórę, MUSISZ również zmienić wygląd swojego ciała, ponieważ oba są ze sobą połączone - są ściśle połączone.
Bóg nie był dobrym programistą zorientowanym obiektowo.
Luźne sprzężenie (szczegółowy przykład)
Pomyśl teraz o ubraniu się rano. Nie lubisz niebieskiego? Bez problemu: zamiast tego możesz założyć czerwoną koszulę. Możesz to zrobić łatwo i bez wysiłku, ponieważ koszula nie jest tak naprawdę połączona z ciałem w taki sam sposób jak skóra. Koszula nie wie ani nie dba o to, jakie ciało ma na sobie . Innymi słowy, możesz zmienić ubranie, bez zmiany ciała.
To kluczowy punkt # 2. Jeśli zmienisz koszulę, nie będziesz zmuszony zmienić ciała - kiedy możesz to zrobić, masz luźne połączenie. Jeśli nie możesz tego zrobić, masz ścisłe połączenie.
To podstawowa koncepcja w pigułce.
Dlaczego to wszystko jest tak ważne?
Jest to ważne, ponieważ oprogramowanie zmienia się cały czas. Mówiąc ogólnie, chcesz mieć możliwość łatwej modyfikacji kodu bez zmiany kodu. Wiem, że to brzmi jak oksymoron, ale proszę o wyrozumiałość.
Praktyczne przykłady łączenia w kodowaniu
Przykłady CSV / JSON / DB: Jeśli ktoś chce otrzymać dane wyjściowe w pliku CSV zamiast JSON itp. Lub jeśli chcesz przejść z MySQL na PostGreSQL, powinieneś być w stanie bardzo łatwo dokonać tych zmian w kodzie, bez konieczności przepisywania cała klasa itp. Innymi słowy, nie chcesz ściśle łączyć aplikacji z konkretną implementacją bazy danych (np. Mysql) lub z konkretnym wyjściem (np. pliki CSV). Ponieważ, jak jest to nieuniknione w oprogramowaniu, nadchodzą zmiany. Kiedy nadejdą, znacznie łatwiej jest, jeśli części kodu są luźno powiązane.
Części samochodowe Przykład: Jeśli ktoś chce ich samochód w czerni , nie powinien mieć przeprojektować cały samochód, aby to zrobić. Samochód i jego części zamienne byłyby idealnym przykładem luźno sprzężonej architektury. Jeśli chcesz wymienić silnik na lepszy, powinieneś być w stanie po prostu usunąć silnik bez większego wysiłku i zamienić go na lepszy. Jeśli twój samochód współpracuje tylko z silnikami Rolls Royce 1234, a nie z innymi silnikami - wtedy twój samochód będzie ściśle połączony z tym silnikiem (Rolls Royce 1234). Byłoby lepiej, gdybyś zmienił wygląd swojego samochodu, aby działał z każdymsilnik, dzięki czemu jest nieco luźniej sprzężony z jego elementami. Jeszcze lepiej byłoby, gdyby Twój samochód mógł pracować bez konieczności używania silnika! Pewna ilość sprzężenia się wydarzy, ale powinieneś pracować, aby zminimalizować ją tak bardzo, jak to możliwe. Czemu? Ponieważ gdy zmieniają się wymagania, nadal powinniśmy być w stanie dostarczać dobrej jakości oprogramowanie, bardzo szybko i pomagają nam w tym luźne połączenia.
Podsumowanie
Krótko mówiąc, luźne sprzężenie ułatwia zmianę kodu. Powyższe odpowiedzi zawierają kod, który warto w tym momencie przeczytać.
Polimorfizm i zasady SOLID
Re: @TimoHuovinen komentuje - koncepcja luźnego sprzężenia idzie w parze z koncepcjami polimorfizmu. Jeśli zrozumiesz podstawową analogię części koszuli / samochodu, będziesz gotowy zrozumieć sens polimorfizmu. Najlepszym sposobem jest w tym miejscu odczytanie próbek kodu dostarczonych przez moich szacownych kolegów w innych odpowiedziach w tym wątku. Jeśli powiem więcej, możesz zostać przeładowany zbyt dużą ilością informacji.
jest to niedoceniane wyjaśnienie dla nowych programistów. Trudno jest przejść przez wielkie słowa, które inni wypowiadają, gdy zrozumiesz podstawy, łatwiej jest przejść do wielkich słów lol
user2763557
6
Są pewne rzeczy, które muszą być ściśle powiązane, a niektóre luźno związane z otoczeniem. Użycie skóry nie jest odpowiednią analogią do ciasnego połączenia. Jeśli uważa się, że skóra jest ściśle połączona z ciałem, to każda inna część. Ciało (jako całość) musi mieć części (ściśle zintegrowane), aby prawidłowo funkcjonować (może tak myśli natura - genialny architekt). Gdyby te części zostały zaprojektowane tak, aby były wymienne (tak proste jak zmiana czapki), wówczas samo znaczenie „ludzkiego” ciała traci swoją definicję. Komentarz 1/2.
lupchiazoem
6
Idąc za przykładem, jeśli skóra ma być wymienna, to głowa również musi być wymienna na nowo. Jeśli tak się stanie, ludzie mogą nie być rozpoznawalni od jednego spotkania do drugiego. Dobrą analogią ścisłego / luźnego sprzężenia byłoby - samochód i jego części, komputer i jego części itp. Jeśli istnieje problem z myszą / klawiaturą komputera, można go zastąpić inną częścią, zamiast uczynić cały komputer bezużytecznym i wyrzuć. Komentarz 2/2.
lupchiazoem
1
@BKSpurgeon Niesamowite wyjaśnienie !! a Twój sposób podania przykładu wyjaśnienia jest również bardzo dobry.
Kiran Joshi
5
Wyjaśniłem bardzo twórczo. Jestem ściśle związany z tą odpowiedzią.
AliN11
72
W projektowaniu obiektowym ilość sprzężeń odnosi się do tego, jak bardzo projekt jednej klasy zależy od projektu innej klasy. Innymi słowy, jak często zmiany w klasie A wiążą się ze zmianami w klasie B? Ścisłe połączenie oznacza, że dwie klasy często się zmieniają, luźne połączenie oznacza, że są one w większości niezależne. Ogólnie zaleca się luźne sprzęganie, ponieważ łatwiej jest je testować i konserwować.
„jak często zmiany w klasie A wiążą się ze zmianami w klasie B?” Potrzebuję krótkiego przykładu dla powyższego zdania?
Kumaresan Perumal,
15
Ogólnie Tight Coupling jest zły, ale przez większość czasu, ponieważ zmniejsza elastyczność i możliwość ponownego użycia kodu, utrudnia zmiany, utrudnia testowanie itp.
Tightly Coupled Object to obiekt, który musi o sobie sporo wiedzieć i zwykle jest w dużym stopniu zależny od siebie. Zmiana jednego obiektu w ściśle powiązanej aplikacji często wymaga zmian w wielu innych obiektach. W małej aplikacji możemy łatwo zidentyfikować zmiany i jest mniejsza szansa na przeoczenie czegoś. Ale w dużych aplikacjach te wzajemne zależności nie zawsze są znane każdemu programistowi lub istnieje szansa, że przegapią zmiany. Ale każdy zestaw luźno powiązanych obiektów nie jest zależny od innych.
Krótko mówiąc, możemy powiedzieć, że luźne sprzęganie jest celem projektowym, który ma na celu zmniejszenie współzależności między komponentami systemu w celu zmniejszenia ryzyka, że zmiany w jednym komponencie będą wymagały zmian w innym komponencie. Luźne sprzężenie jest znacznie bardziej ogólną koncepcją mającą na celu zwiększenie elastyczności systemu, uczynienie go łatwiejszym w utrzymaniu i sprawienie, że cała struktura będzie bardziej „stabilna”.
Łączenie odnosi się do stopnia bezpośredniej wiedzy, jaką jeden element ma na drugim. możemy powiedzieć np .: A i B, tylko B zmienia swoje zachowanie tylko wtedy, gdy A zmienia swoje zachowanie. Luźno sprzężony system można łatwo rozbić na definiowalne elementy.
Zgodnie z powyższą definicją obiekt ściśle sprzężony to obiekt, który musi wiedzieć o innych obiektach i zwykle jest wysoce zależny od wzajemnych interfejsów.
Kiedy zmieniamy jeden obiekt w ściśle powiązanej aplikacji, często wymaga to zmiany wielu innych obiektów. W małej aplikacji nie ma problemu, dzięki czemu możemy łatwo zidentyfikować zmianę. Ale w przypadku dużych aplikacji te wzajemne zależności nie zawsze są znane każdemu konsumentowi lub innemu deweloperowi, lub istnieje wiele szans na przyszłe zmiany.
Weźmy kod demonstracyjny koszyka na zakupy, aby zrozumieć ścisłe połączenie:
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);
}
}
}
Problemy z powyższym przykładem
Tight Coupling stwarza pewne trudności.
W tym przypadku OrderTotal()metody podają nam pełną kwotę na bieżące pozycje wózków. Jeśli chcemy dodać funkcje zniżek w tym systemie koszykowym. W powyższym kodzie jest to bardzo trudne, ponieważ musimy wprowadzać zmiany w każdej klasie, ponieważ jest ona bardzo ściśle powiązana.
Rozumiem, że architektura ściśle sprzężona nie zapewnia dużej elastyczności w zakresie zmian w porównaniu z architekturą luźno sprzężoną.
Ale w przypadku luźno powiązanych architektur, formatów komunikatów lub platform operacyjnych lub przebudowy logiki biznesowej nie ma wpływu na drugi koniec. Jeśli system zostanie zdjęty z powodu zmiany, oczywiście drugi koniec nie będzie mógł uzyskać dostępu do usługi przez pewien czas, ale poza tym niezmieniony koniec może wznowić wymianę komunikatów, tak jak przed zmianą.
Ścisłe połączenie oznacza, że jedna klasa jest zależna od innej klasy. Luźne sprzężenie oznacza, że jedna klasa zależy od interfejsu, a nie klasy.
W ścisłym sprzężeniu w metodach deklarowana jest na stałe zależność.
W luźnym sprzężeniu musimy przekazać zależność zewnętrznie w czasie wykonywania, zamiast na stałe zakodować. (Systemy z luźną parą używają interfejsu w celu zmniejszenia zależności od klasy.)
Na przykład mamy system, który może wysyłać dane wyjściowe na dwa lub więcej sposobów, takie jak dane wyjściowe JSON, dane wyjściowe CSV itp.
Tight Coupled
publicinterfaceOutputGenerator{publicvoid generateOutput();}publicclassCSVOutputGeneratorimplementsOutputGenerator{publicvoid generateOutput(){System.out.println("CSV Output Generator");}}publicclassJSONOutputGeneratorimplementsOutputGenerator{publicvoid generateOutput(){System.out.println("JSON Output Generator");}}// In Other Code, we write Output Generator like...publicclassClass1{publicvoid 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 =newCSVOutputGenerator();
output.generateOutput();}}
W powyższym przykładzie, jeśli chcemy zmienić dane wyjściowe w JSON, musimy znaleźć i zmienić cały kod, ponieważ klasa 1 jest ściśle sprzężona z klasą CSVOutputGenerator.
Loose Coupled
publicinterfaceOutputGenerator{publicvoid generateOutput();}publicclassCSVOutputGeneratorimplementsOutputGenerator{publicvoid generateOutput(){System.out.println("CSV Output Generator");}}publicclassJSONOutputGeneratorimplementsOutputGenerator{publicvoid generateOutput(){System.out.println("JSON Output Generator");}}// In Other Code, we write Output Generator like...publicclassClass1{publicvoid 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 classOutputGenerator outputGenerator = outputGenerator;
output.generateOutput();}}
Istnieją pewne narzędzia zapewniające wstrzykiwanie zależności za pośrednictwem ich biblioteki, na przykład w .net mamy bibliotekę ninject .
Jeśli idziesz dalej w Javie, wiosna zapewnia te możliwości.
Obiekty luźno sprzężone można tworzyć, wprowadzając interfejsy do kodu, tak właśnie robią te źródła.
Powiedz w swoim kodzie, że piszesz
Myclass m = new Myclass();
teraz to stwierdzenie w twojej metodzie mówi, że jesteś od myclasstego zależny, nazywa się ściśle powiązane. Teraz zapewnisz zastrzyk konstruktora lub zastrzyk właściwości i obiekt tworzenia wystąpienia, a następnie zostanie on luźno sprzężony.
Jest tu wiele fajnych odpowiedzi przy użyciu analogii, ale kolega z pracy podał mi przykład, który podobał mi się bardziej niż wszystkie wymienione tutaj ... Oczy i okulary!
Ciasne połączenie
Mocne połączenie byłoby oczami. Jeśli chcę naprawić swój wzrok, przeszczep oka jest bardzo drogi i wiąże się z dużym ryzykiem. Ale co jeśli projektant (będący rasą ludzką) znalazł lepszy sposób. Dodaj funkcję, która jest luźno połączona z ciałem, dzięki czemu można ją łatwo zmienić! (tak .. okulary)
Luźne powiązanie
Mogę z łatwością wymienić okulary bez naruszania podstawowej wizji. Mogę zdjąć okulary, a moja wizja będzie taka, jaka była wcześniej (nie lepiej ani gorzej). Używanie różnych par okularów zmienia sposób, w jaki postrzegamy świat oczami, bez ryzyka i łatwej konserwacji.
Podsumowanie
Więc następnym razem ktoś zapyta: „kogo to obchodzi, czy mój kod jest ściśle powiązany?” Odpowiedzią jest wysiłek zmiany, wysiłek utrzymania i ryzyko zmiany.
Jak to się robi w C #? Interfejsy i wstrzykiwanie zależności!
EDYTOWAĆ
To również dobry przykład wzoru dekoratora, w którym oczy są klasą, którą dekorujemy, spełniając wymagania dotyczące interfejsu, ale zapewniając różne funkcje (np. Okulary przeciwsłoneczne, okulary do czytania, szkła powiększające dla jubilerów itp.)
Luźne sprzężenie jest odpowiedzią na zakodowane w starym stylu zależności i związane z nimi problemy, takie jak częsta rekompilacja, gdy coś się zmienia i ponowne użycie kodu. Nacisk kładzie się na implementację logiki procesu roboczego w komponentach i unikanie tam specyficznego dla rozwiązania kodu połączenia.
Loose Coupling = IoC.
Zobacz to dla łatwiejszego wyjaśnienia.
Nie sądzę, aby luźne sprzężenie było równoznaczne z odwróceniem kontroli. Odwrócenie kontroli jest bardzo przydatną techniką zmniejszania sprzężenia twojego projektu, ale istnieje wiele innych technik.
Don Kirkby
2
Luźne sprzęganie to proces nadawania zależności, której klasa potrzebuje pośrednio, bez dostarczania wszystkich informacji o zależności (tj. Z interfejsu) w przypadku, gdy ścisłe sprzężenie dajesz bezpośrednio w zależności, która nie jest dobrym sposobem kodowania.
Chodzi o współczynnik zależności klas od innych, który jest tak niski w luźno powiązanych i tak wysoki w ciasno powiązanych. Aby być bardziej przejrzystym w architekturze zorientowanej na usługi, usługi są luźno połączone ze sobą w stosunku do monolitów, których zależność między klasami jest celowo
Jeśli tworzenie / istnienie obiektu zależy od innego obiektu, którego nie można dostosować, jego ścisłe połączenie. A jeśli zależność można dostosować, jej luźne połączenie. Rozważ przykład w Javie:
class Car {
private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
// Other parts
public Car() {
// implemenation
}
}
Klient Carklasy może utworzyć taki z TYLKO silnikiem „X_COMPANY”.
Rozważ zerwanie tego sprzężenia z możliwością zmiany tego:
class Car {
private Engine engine;
// Other members
public Car( Engine engine ) { // this car can be created with any Engine type
this.engine = engine;
}
}
Teraz a Carnie jest zależne od silnika „X_COMPANY”, ponieważ można go tworzyć z typami.
Uwaga specyficzna dla Javy: używanie interfejsów Java tylko w celu rozprzęgania nie jest właściwym podejściem do projektowania. W Javie interfejs ma cel - działać jak umowa, która w sposób wewnętrzny zapewnia zachowanie / korzyść z rozłączania.
Komentarz Billa Rosmusa w przyjętej odpowiedzi ma dobre wytłumaczenie.
Ścisłe połączenie oznacza, że klasy i obiekty są od siebie zależne. Zasadniczo ścisłe sprzężenie zwykle nie jest dobre, ponieważ zmniejsza elastyczność i możliwość ponownego użycia kodu, natomiast luźne sprzężenie oznacza zmniejszenie zależności klasy, która bezpośrednio używa innej klasy.
Ścisłe sprzężenie Ścisłe sprzężenie to obiekt, który musi wiedzieć o innych obiektach i zwykle jest wysoce zależny od wzajemnych interfejsów. Zmiana jednego obiektu w ściśle powiązanej aplikacji często wymaga zmian wielu innych obiektów. W małych aplikacjach możemy łatwo zidentyfikować zmiany i jest mniejsza szansa, że coś przeoczysz. Ale w dużych aplikacjach te wzajemne zależności nie zawsze są znane każdemu programistowi i istnieje szansa przeoczenia zmian. Przykład:
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());
}
}
W powyższym przykładzie kod zdefiniowany przez tego rodzaju implementację wykorzystuje luźne sprzężenie i jest zalecany, ponieważ klasa B musi przejść przez klasę A, aby uzyskać stan, w którym reguły są egzekwowane. Jeśli klasa A zostanie zmieniona wewnętrznie, klasa B nie ulegnie zniszczeniu, ponieważ wykorzystuje tylko klasę A jako sposób komunikacji.
Odpowiedzi:
Ścisłe sprzężenie ma miejsce, gdy grupa klas jest od siebie wysoce zależna.
Ten scenariusz powstaje, gdy klasa przyjmuje zbyt wiele obowiązków lub gdy jedna troska jest rozłożona na wiele klas, zamiast mieć własną klasę.
Luźne sprzężenie osiąga się za pomocą konstrukcji, która promuje pojedynczą odpowiedzialność i rozdzielenie problemów.
Luźno sprzężoną klasę można konsumować i testować niezależnie od innych (konkretnych) klas.
Interfejsy to potężne narzędzie do oddzielania. Klasy mogą komunikować się za pośrednictwem interfejsów, a nie innych konkretnych klas, a każda klasa może znajdować się na drugim końcu tej komunikacji, po prostu implementując interfejs.
Przykład ciasnego połączenia:
Przykład luźnego sprzężenia:
Kolejny przykład tutaj .
źródło
Objaśnienie bez ŻADNEGO kodu
Przykład podsumowania:
Kapelusz jest „luźno połączony” z ciałem. Oznacza to, że możesz łatwo zdjąć czapkę bez wprowadzania zmian w osobie / ciele. Kiedy możesz to zrobić, masz „luźne połączenie”. Zobacz poniżej opracowanie.
Szczelne połączenie (szczegółowy przykład)
Pomyśl o swojej skórze. Przylega do twojego ciała. Pasuje jak rękawiczka. Ale co, jeśli chcesz zmienić kolor skóry z białego na zielony? Czy potrafisz sobie wyobrazić, jak bolesne byłoby złuszczanie skóry, farbowanie, a następnie wklejanie z powrotem itp.? Zmiana skóry jest trudna, ponieważ jest ściśle związana z ciałem. Po prostu nie możesz łatwo wprowadzać zmian. Trzeba by zasadniczo przeprojektować człowieka, aby było to możliwe.
Bóg nie był dobrym programistą zorientowanym obiektowo.
Luźne sprzężenie (szczegółowy przykład)
Pomyśl teraz o ubraniu się rano. Nie lubisz niebieskiego? Bez problemu: zamiast tego możesz założyć czerwoną koszulę. Możesz to zrobić łatwo i bez wysiłku, ponieważ koszula nie jest tak naprawdę połączona z ciałem w taki sam sposób jak skóra. Koszula nie wie ani nie dba o to, jakie ciało ma na sobie . Innymi słowy, możesz zmienić ubranie, bez zmiany ciała.
To podstawowa koncepcja w pigułce.
Dlaczego to wszystko jest tak ważne?
Jest to ważne, ponieważ oprogramowanie zmienia się cały czas. Mówiąc ogólnie, chcesz mieć możliwość łatwej modyfikacji kodu bez zmiany kodu. Wiem, że to brzmi jak oksymoron, ale proszę o wyrozumiałość.
Praktyczne przykłady łączenia w kodowaniu
Przykłady CSV / JSON / DB: Jeśli ktoś chce otrzymać dane wyjściowe w pliku CSV zamiast JSON itp. Lub jeśli chcesz przejść z MySQL na PostGreSQL, powinieneś być w stanie bardzo łatwo dokonać tych zmian w kodzie, bez konieczności przepisywania cała klasa itp. Innymi słowy, nie chcesz ściśle łączyć aplikacji z konkretną implementacją bazy danych (np. Mysql) lub z konkretnym wyjściem (np. pliki CSV). Ponieważ, jak jest to nieuniknione w oprogramowaniu, nadchodzą zmiany. Kiedy nadejdą, znacznie łatwiej jest, jeśli części kodu są luźno powiązane.
Części samochodowe Przykład: Jeśli ktoś chce ich samochód w czerni , nie powinien mieć przeprojektować cały samochód, aby to zrobić. Samochód i jego części zamienne byłyby idealnym przykładem luźno sprzężonej architektury. Jeśli chcesz wymienić silnik na lepszy, powinieneś być w stanie po prostu usunąć silnik bez większego wysiłku i zamienić go na lepszy. Jeśli twój samochód współpracuje tylko z silnikami Rolls Royce 1234, a nie z innymi silnikami - wtedy twój samochód będzie ściśle połączony z tym silnikiem (Rolls Royce 1234). Byłoby lepiej, gdybyś zmienił wygląd swojego samochodu, aby działał z każdymsilnik, dzięki czemu jest nieco luźniej sprzężony z jego elementami. Jeszcze lepiej byłoby, gdyby Twój samochód mógł pracować bez konieczności używania silnika! Pewna ilość sprzężenia się wydarzy, ale powinieneś pracować, aby zminimalizować ją tak bardzo, jak to możliwe. Czemu? Ponieważ gdy zmieniają się wymagania, nadal powinniśmy być w stanie dostarczać dobrej jakości oprogramowanie, bardzo szybko i pomagają nam w tym luźne połączenia.
Podsumowanie
Krótko mówiąc, luźne sprzężenie ułatwia zmianę kodu. Powyższe odpowiedzi zawierają kod, który warto w tym momencie przeczytać.
Polimorfizm i zasady SOLID
Re: @TimoHuovinen komentuje - koncepcja luźnego sprzężenia idzie w parze z koncepcjami polimorfizmu. Jeśli zrozumiesz podstawową analogię części koszuli / samochodu, będziesz gotowy zrozumieć sens polimorfizmu. Najlepszym sposobem jest w tym miejscu odczytanie próbek kodu dostarczonych przez moich szacownych kolegów w innych odpowiedziach w tym wątku. Jeśli powiem więcej, możesz zostać przeładowany zbyt dużą ilością informacji.
Uznanie autorstwa .
źródło
W projektowaniu obiektowym ilość sprzężeń odnosi się do tego, jak bardzo projekt jednej klasy zależy od projektu innej klasy. Innymi słowy, jak często zmiany w klasie A wiążą się ze zmianami w klasie B? Ścisłe połączenie oznacza, że dwie klasy często się zmieniają, luźne połączenie oznacza, że są one w większości niezależne. Ogólnie zaleca się luźne sprzęganie, ponieważ łatwiej jest je testować i konserwować.
Pomocny może być ten artykuł Martina Fowlera (PDF) .
źródło
Ogólnie Tight Coupling jest zły, ale przez większość czasu, ponieważ zmniejsza elastyczność i możliwość ponownego użycia kodu, utrudnia zmiany, utrudnia testowanie itp.
Tightly Coupled Object to obiekt, który musi o sobie sporo wiedzieć i zwykle jest w dużym stopniu zależny od siebie. Zmiana jednego obiektu w ściśle powiązanej aplikacji często wymaga zmian w wielu innych obiektach. W małej aplikacji możemy łatwo zidentyfikować zmiany i jest mniejsza szansa na przeoczenie czegoś. Ale w dużych aplikacjach te wzajemne zależności nie zawsze są znane każdemu programistowi lub istnieje szansa, że przegapią zmiany. Ale każdy zestaw luźno powiązanych obiektów nie jest zależny od innych.
Krótko mówiąc, możemy powiedzieć, że luźne sprzęganie jest celem projektowym, który ma na celu zmniejszenie współzależności między komponentami systemu w celu zmniejszenia ryzyka, że zmiany w jednym komponencie będą wymagały zmian w innym komponencie. Luźne sprzężenie jest znacznie bardziej ogólną koncepcją mającą na celu zwiększenie elastyczności systemu, uczynienie go łatwiejszym w utrzymaniu i sprawienie, że cała struktura będzie bardziej „stabilna”.
Łączenie odnosi się do stopnia bezpośredniej wiedzy, jaką jeden element ma na drugim. możemy powiedzieć np .: A i B, tylko B zmienia swoje zachowanie tylko wtedy, gdy A zmienia swoje zachowanie. Luźno sprzężony system można łatwo rozbić na definiowalne elementy.
źródło
Kiedy dwa obiekty są luźno połączone, mogą one oddziaływać, ale mają bardzo małą wiedzę o sobie.
Luźno sprzężone konstrukcje pozwalają nam budować elastyczne systemy OO, które mogą obsługiwać zmiany.
Wzorzec projektowy obserwatora jest dobrym przykładem luźnego powiązania klas, można go obejrzeć w Wikipedii .
źródło
Fragment mojego postu na blogu o sprzężeniu:
Co to jest ścisłe połączenie : -
Zgodnie z powyższą definicją obiekt ściśle sprzężony to obiekt, który musi wiedzieć o innych obiektach i zwykle jest wysoce zależny od wzajemnych interfejsów.
Kiedy zmieniamy jeden obiekt w ściśle powiązanej aplikacji, często wymaga to zmiany wielu innych obiektów. W małej aplikacji nie ma problemu, dzięki czemu możemy łatwo zidentyfikować zmianę. Ale w przypadku dużych aplikacji te wzajemne zależności nie zawsze są znane każdemu konsumentowi lub innemu deweloperowi, lub istnieje wiele szans na przyszłe zmiany.
Weźmy kod demonstracyjny koszyka na zakupy, aby zrozumieć ścisłe połączenie:
Problemy z powyższym przykładem
Tight Coupling stwarza pewne trudności.
W tym przypadku
OrderTotal()
metody podają nam pełną kwotę na bieżące pozycje wózków. Jeśli chcemy dodać funkcje zniżek w tym systemie koszykowym. W powyższym kodzie jest to bardzo trudne, ponieważ musimy wprowadzać zmiany w każdej klasie, ponieważ jest ona bardzo ściśle powiązana.źródło
Luźne sprzężenie oznacza, że stopień zależności między dwoma składnikami jest bardzo niski.
Przykład: GSM SIM
Ścisłe połączenie oznacza, że stopień zależności między dwoma elementami jest bardzo wysoki.
Przykład: CDMA Mobile
źródło
Rozumiem, że architektura ściśle sprzężona nie zapewnia dużej elastyczności w zakresie zmian w porównaniu z architekturą luźno sprzężoną.
Ale w przypadku luźno powiązanych architektur, formatów komunikatów lub platform operacyjnych lub przebudowy logiki biznesowej nie ma wpływu na drugi koniec. Jeśli system zostanie zdjęty z powodu zmiany, oczywiście drugi koniec nie będzie mógł uzyskać dostępu do usługi przez pewien czas, ale poza tym niezmieniony koniec może wznowić wymianę komunikatów, tak jak przed zmianą.
źródło
Ścisłe połączenie oznacza, że jedna klasa jest zależna od innej klasy.
Luźne sprzężenie oznacza, że jedna klasa zależy od interfejsu, a nie klasy.
W ścisłym sprzężeniu w metodach deklarowana jest na stałe zależność.
W luźnym sprzężeniu musimy przekazać zależność zewnętrznie w czasie wykonywania, zamiast na stałe zakodować. (Systemy z luźną parą używają interfejsu w celu zmniejszenia zależności od klasy.)
Na przykład mamy system, który może wysyłać dane wyjściowe na dwa lub więcej sposobów, takie jak dane wyjściowe JSON, dane wyjściowe CSV itp.
Tight Coupled
W powyższym przykładzie, jeśli chcemy zmienić dane wyjściowe w JSON, musimy znaleźć i zmienić cały kod, ponieważ klasa 1 jest ściśle sprzężona z klasą CSVOutputGenerator.
Loose Coupled
źródło
Istnieją pewne narzędzia zapewniające wstrzykiwanie zależności za pośrednictwem ich biblioteki, na przykład w .net mamy bibliotekę ninject .
Jeśli idziesz dalej w Javie, wiosna zapewnia te możliwości.
Obiekty luźno sprzężone można tworzyć, wprowadzając interfejsy do kodu, tak właśnie robią te źródła.
Powiedz w swoim kodzie, że piszesz
teraz to stwierdzenie w twojej metodzie mówi, że jesteś od
myclass
tego zależny, nazywa się ściśle powiązane. Teraz zapewnisz zastrzyk konstruktora lub zastrzyk właściwości i obiekt tworzenia wystąpienia, a następnie zostanie on luźno sprzężony.źródło
Jest tu wiele fajnych odpowiedzi przy użyciu analogii, ale kolega z pracy podał mi przykład, który podobał mi się bardziej niż wszystkie wymienione tutaj ... Oczy i okulary!
Ciasne połączenie
Mocne połączenie byłoby oczami. Jeśli chcę naprawić swój wzrok, przeszczep oka jest bardzo drogi i wiąże się z dużym ryzykiem. Ale co jeśli projektant (będący rasą ludzką) znalazł lepszy sposób. Dodaj funkcję, która jest luźno połączona z ciałem, dzięki czemu można ją łatwo zmienić! (tak .. okulary)
Luźne powiązanie
Mogę z łatwością wymienić okulary bez naruszania podstawowej wizji. Mogę zdjąć okulary, a moja wizja będzie taka, jaka była wcześniej (nie lepiej ani gorzej). Używanie różnych par okularów zmienia sposób, w jaki postrzegamy świat oczami, bez ryzyka i łatwej konserwacji.
Podsumowanie
Więc następnym razem ktoś zapyta: „kogo to obchodzi, czy mój kod jest ściśle powiązany?” Odpowiedzią jest wysiłek zmiany, wysiłek utrzymania i ryzyko zmiany.
Jak to się robi w C #? Interfejsy i wstrzykiwanie zależności!
EDYTOWAĆ
To również dobry przykład wzoru dekoratora, w którym oczy są klasą, którą dekorujemy, spełniając wymagania dotyczące interfejsu, ale zapewniając różne funkcje (np. Okulary przeciwsłoneczne, okulary do czytania, szkła powiększające dla jubilerów itp.)
źródło
Luźne sprzężenie jest odpowiedzią na zakodowane w starym stylu zależności i związane z nimi problemy, takie jak częsta rekompilacja, gdy coś się zmienia i ponowne użycie kodu. Nacisk kładzie się na implementację logiki procesu roboczego w komponentach i unikanie tam specyficznego dla rozwiązania kodu połączenia.
Loose Coupling = IoC. Zobacz to dla łatwiejszego wyjaśnienia.
źródło
Luźne sprzęganie to proces nadawania zależności, której klasa potrzebuje pośrednio, bez dostarczania wszystkich informacji o zależności (tj. Z interfejsu) w przypadku, gdy ścisłe sprzężenie dajesz bezpośrednio w zależności, która nie jest dobrym sposobem kodowania.
źródło
Chodzi o współczynnik zależności klas od innych, który jest tak niski w luźno powiązanych i tak wysoki w ciasno powiązanych. Aby być bardziej przejrzystym w architekturze zorientowanej na usługi, usługi są luźno połączone ze sobą w stosunku do monolitów, których zależność między klasami jest celowo
źródło
Jeśli tworzenie / istnienie obiektu zależy od innego obiektu, którego nie można dostosować, jego ścisłe połączenie. A jeśli zależność można dostosować, jej luźne połączenie. Rozważ przykład w Javie:
Klient
Car
klasy może utworzyć taki z TYLKO silnikiem „X_COMPANY”.Rozważ zerwanie tego sprzężenia z możliwością zmiany tego:
Teraz a
Car
nie jest zależne od silnika „X_COMPANY”, ponieważ można go tworzyć z typami.Uwaga specyficzna dla Javy: używanie interfejsów Java tylko w celu rozprzęgania nie jest właściwym podejściem do projektowania. W Javie interfejs ma cel - działać jak umowa, która w sposób wewnętrzny zapewnia zachowanie / korzyść z rozłączania.
Komentarz Billa Rosmusa w przyjętej odpowiedzi ma dobre wytłumaczenie.
źródło
Ścisłe połączenie oznacza, że klasy i obiekty są od siebie zależne. Zasadniczo ścisłe sprzężenie zwykle nie jest dobre, ponieważ zmniejsza elastyczność i możliwość ponownego użycia kodu, natomiast luźne sprzężenie oznacza zmniejszenie zależności klasy, która bezpośrednio używa innej klasy.
Ścisłe sprzężenie Ścisłe sprzężenie to obiekt, który musi wiedzieć o innych obiektach i zwykle jest wysoce zależny od wzajemnych interfejsów. Zmiana jednego obiektu w ściśle powiązanej aplikacji często wymaga zmian wielu innych obiektów. W małych aplikacjach możemy łatwo zidentyfikować zmiany i jest mniejsza szansa, że coś przeoczysz. Ale w dużych aplikacjach te wzajemne zależności nie zawsze są znane każdemu programistowi i istnieje szansa przeoczenia zmian. Przykład:
W powyższym przykładzie kod zdefiniowany przez tego rodzaju implementację wykorzystuje luźne sprzężenie i jest zalecany, ponieważ klasa B musi przejść przez klasę A, aby uzyskać stan, w którym reguły są egzekwowane. Jeśli klasa A zostanie zmieniona wewnętrznie, klasa B nie ulegnie zniszczeniu, ponieważ wykorzystuje tylko klasę A jako sposób komunikacji.
źródło