В чем разница между слабой связью и жесткой связью в объектно-ориентированной парадигме?
Кто-нибудь может описать точную разницу между слабой связью и сильной связью в объектно-ориентированной парадигме?
18 ответов
Тесная связь - это когда группа классов сильно зависит друг от друга.
Этот сценарий возникает, когда класс принимает на себя слишком много обязанностей или когда одна проблема распространяется на многие классы, а не на собственный класс.
Слабое сцепление достигается с помощью конструкции, которая способствует единоличной ответственности и разделению интересов.
Слабосвязанный класс может потребляться и тестироваться независимо от других (конкретных) классов.
Интерфейсы являются мощным инструментом для разделения. Классы могут взаимодействовать через интерфейсы, а не через другие конкретные классы, и любой класс может находиться на другом конце этого взаимодействия, просто реализуя интерфейс.
Пример жесткой связи:
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)
{
}
}
Пример слабой связи:
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 : IDatabase
{
public void AddRow(string Table, string Value)
{
}
}
Еще один пример здесь.
Объяснение концепции без кода
Сводный пример:
Шляпа "слабо связана" с телом. Это означает, что вы можете легко снять шляпу, не внося никаких изменений в человека / тело. Когда вы можете сделать это, у вас есть "слабая связь". Смотрите ниже для уточнения.
Герметичное соединение (подробный пример)
Подумай о своей коже. Это прилипло к вашему телу. Это подходит как перчатка. Но что, если вы хотите изменить цвет вашей кожи, скажем, с белого на черный? Можете ли вы представить себе, насколько больно было бы отслоить кожу, покрасить ее, а затем снова наклеить на нее и т. Д.? Изменить кожу сложно, потому что она тесно связана с вашим телом. Вы просто не можете легко вносить изменения. Вы должны кардинально изменить дизайн человека, чтобы сделать это возможным.
- Ключевой момент № 1: Другими словами, если вы хотите изменить кожу, вы также должны были бы изменить дизайн вашего тела, потому что они соединены вместе - они тесно связаны.
Бог не был хорошим объектно-ориентированным программистом.
Слабая связь (подробный пример)
А теперь подумай одеться утром. Тебе не нравится синий? Нет проблем: вместо этого вы можете надеть красную рубашку. Вы можете сделать это легко и без усилий, потому что рубашка на самом деле не связана с вашим телом так же, как ваша кожа. Рубашка не знает и не заботится о том, на каком она теле. Другими словами, вы можете переодеться, не меняя своего тела.
- Это ключевой момент № 2. Если вы меняете свою рубашку, то вы не обязаны менять свое тело - когда вы можете это сделать, тогда у вас слабая связь. Когда вы не можете этого сделать, значит, у вас сильная связь.
Это основная концепция в двух словах.
Почему все это важно?
Это важно, потому что программное обеспечение постоянно меняется. Вообще говоря, вы хотите иметь возможность легко изменить свой код.
например, практические примеры
- Если кто-то хочет выводить их в CSV-файле, а не в JSON и т. Д., Или если вы хотите переключиться с MySQL на PostGreSQL, вы сможете очень легко внести эти изменения в свой код без необходимости переписывать весь класс и тратить 10 часов. отладки. Другими словами, вы не хотите тесно связывать ваше приложение с конкретной реализацией базы данных (например, Mysql) или с конкретным выводом (например, CSV-файлы). Потому что, как это неизбежно в программном обеспечении, изменения придут. Когда они приходят, гораздо проще, если ваши части кода слабо связаны.
- Если кто-то хочет свою машину в черном цвете, вам не нужно переделывать всю машину, чтобы сделать это. Автомобиль и его запчасти будут отличным примером слабо связанной архитектуры (согласно комментариям @ mnmopazem). Если вы хотите заменить свой двигатель на более качественный, вы сможете просто снять его без особых усилий и заменить его на лучший. Если ваш автомобиль работает только с двигателями Rolls Royce ABC1234 и без других двигателей - то ваш автомобиль будет тесно связан с этим двигателем (Rolls Royce ABC1234). (Кстати, если это ваш пароль, то позор вам). Было бы лучше, если бы вы изменили конструкцию своего автомобиля, чтобы он работал с любым двигателем, чтобы он был немного слабее связан с его компонентами. Еще лучше было бы, если бы ваша машина могла работать без двигателя вообще! Должна произойти некоторая взаимосвязь, но вам следует постараться свести ее к минимуму. Зачем? Потому что, когда требования меняются, мы все равно должны иметь возможность поставлять качественное программное обеспечение, очень быстро, и нам помогает в этой цели слабая связь.
Резюме
Короче говоря, слабая связь облегчает изменение кода. Ответы выше предоставляют некоторый код, который стоит прочитать на данный момент.
В объектно-ориентированном дизайне величина связи относится к тому, насколько дизайн одного класса зависит от дизайна другого класса. Другими словами, как часто изменения в классе A связаны с изменениями в классе B? Тесная связь означает, что два класса часто меняются вместе, слабая связь означает, что они в основном независимы. Как правило, слабая связь рекомендуется, потому что ее легче тестировать и обслуживать.
Вы можете найти эту статью Мартина Фаулера (PDF) полезной.
Запрограммировать разницу между плотной и слабой муфтой?
Тесная связь между объектами Java
class Traveler
{
Car c=new Car();
void startJourney()
{
c.move();
}
}
class Car
{
void move()
{
// logic...
}
}
Слабая связь между объектами Java
class Traveler
{
Vehicle v;
public void setV(Vehicle v)
{
this.v = v;
}
void startJourney()
{
v.move();
}
}
// ========================= Интерфейс ====================== ==============
Interface Vehicle
{
void move();
}
// ==================== Интерфейс машины для реализации нескольких классов. Первый класс ====
class Car implements Vehicle
{
public void move()
{
// logic
}
}
// =================== Второй класс ================
class Bike implements Vehicle
{
public void move()
{
// logic
}
}
Плотное соединение означает, что один класс зависит от другого класса. Свободная связь означает, что один класс зависит от интерфейса скорее, чем класс.
В тесной связи есть жестко закодированная зависимость, объявленная в методах. В случае слабой связи мы должны передавать зависимость внешне во время выполнения, а не жестко закодировать.(Системы свободной пары используют интерфейс для уменьшения зависимости от класса).
Например, у нас есть система, которая может отправлять вывод двумя или более способами, такими как JSON-Output, CSV-Output и т. Д.
Плотно соединенный
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();
}
}
В целом, Tight Coupling плохо работает, но в большинстве случаев потому, что он снижает гибкость и возможность повторного использования кода, значительно усложняет изменения, затрудняет тестирование и т. Д.
Тесно связанный объект - это объект, который должен знать немного друг о друге и обычно сильно зависит от интерфейсов друг друга. Изменение одного объекта в тесно связанном приложении часто требует изменений ряда других объектов. В небольшом приложении мы можем легко идентифицировать изменения и меньше шансов что-либо пропустить. Но в больших приложениях эти взаимозависимости не всегда известны каждому программисту, или есть шанс пропустить изменения. Но каждый набор слабо связанных объектов не зависит от других.
Короче говоря, мы можем сказать, что слабая связь - это цель разработки, которая направлена на уменьшение взаимозависимостей между компонентами системы с целью снижения риска того, что изменения в одном компоненте потребуют изменений в любом другом компоненте. Слабая связь - это гораздо более общая концепция, предназначенная для повышения гибкости системы, повышения ее удобства обслуживания и повышения стабильности всей платформы.
Соединение относится к степени непосредственного знания, которое один элемент имеет другой. Например, мы можем сказать: A и B, только B меняет свое поведение, только когда A меняет свое поведение. Слабосвязанная система может быть легко разбита на определяемые элементы.
Когда два объекта слабо связаны, они могут взаимодействовать, но очень мало знают друг о друге.
Слабосвязанные конструкции позволяют нам создавать гибкие ОО-системы, способные справляться с изменениями.
Шаблон проектирования Observer является хорошим примером для того, чтобы сделать классы слабо связанными, вы можете посмотреть его в Википедии.
Слабая связь означает, что степень зависимости между двумя компонентами очень низкая. Ex.GSM SIM Тесная связь означает, что степень зависимости между двумя компонентами очень высокая. ех. CDMA Mobile
Выдержка из моего блога о связи:
Что такое жесткая муфта:-
Как указано выше, Tightly Coupled Object - это объект, который должен знать о других объектах и обычно сильно зависит от интерфейсов друг друга.
Когда мы часто меняем один объект в тесно связанном приложении, это требует изменений ряда других объектов. В небольшом приложении нет проблем, мы можем легко определить изменение. Но в случае больших приложений эти взаимозависимости не всегда известны каждому потребителю или другим разработчикам, или существует большая вероятность будущих изменений.
Давайте возьмем демонстрационный код корзины для покупок, чтобы понять тесную связь:
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);
}
}
}
Проблемы с приведенным выше примером
Плотная муфта создает некоторые трудности.
Вот, OrderTotal()
методы, это дать нам полную сумму для текущих предметов тележек. Если мы хотим добавить функции скидок в эту систему корзины. Это очень трудно сделать в приведенном выше коде, потому что мы должны вносить изменения в каждый класс, так как он очень тесно связан.
Здесь есть много хороших ответов с использованием аналогий, но один знакомый на работе дал мне пример, который мне понравился больше, чем все упомянутые здесь... Глаза и очки!
Тесная связь
Тесная связь была бы глазами. Если я хочу исправить свое зрение, мне очень дорого сделать пересадку глаза, и у меня довольно много риска. Но что, если дизайнер (будучи человеческим родом) нашел лучший путь? Добавить функцию, которая loosely coupled
к телу, так что это может быть легко изменено! (да.. очки)
Слабая связь
Я могу легко заменить свои очки, не нарушая моего основного видения. Я могу снять очки, и мое зрение будет таким, как было раньше (не лучше и не хуже). Использование разных пар очков меняет то, как мы видим мир нашими глазами, с небольшим риском и легкой ремонтопригодностью.
Резюме
Так что в следующий раз кто-то спросит вас "кого это волнует, если мой код тесно связан?" Ответ - все об усилиях, чтобы измениться, усилие поддержать и риск изменения.
Так как же это сделать в C#? Interfaces
а также Dependency Injection
!
РЕДАКТИРОВАТЬ
Это хороший пример шаблона Decorator, где глаза - это класс, который мы украшаем, отвечая требованиям интерфейса, но предоставляя различные функциональные возможности (например, солнцезащитные очки, очки для чтения, лупы для ювелиров и т. Д.)
Насколько я понимаю, тесно связанная архитектура не обеспечивает большой гибкости для изменений по сравнению со слабосвязанной архитектурой.
Но в случае слабосвязанных архитектур, форматов сообщений или операционных платформ или модернизации бизнес-логики не влияет на другой конец. Если система будет отключена для обновления, то, конечно, другой конец не сможет получить доступ к службе некоторое время, но кроме этого, неизменный конец может возобновить обмен сообщениями, как это было до обновления.
Речь идет о степени зависимости классов от других, которая так низка в слабо связанных и так высока в тесно связанных. Чтобы было понятно в архитектуре ориентации на сервисы, сервисы слабо связаны друг с другом против монолитного, классовая зависимость которого является друг от друга целью
Существуют определенные инструменты, которые обеспечивают внедрение зависимостей через их библиотеку, например, в.net у нас есть библиотека ninject.
Если вы идете дальше в Java, то Spring предоставляет эти возможности.
Слабосвязанные объекты могут быть созданы путем введения интерфейсов в ваш код, вот что делают эти источники.
Скажи в своем коде вы пишете
Myclass m = new Myclass();
Теперь это утверждение в вашем методе говорит, что вы зависите от myclass
это называется тесно связанным. Теперь вы предоставляете некоторую инъекцию в конструктор, или инъекцию свойства и создание экземпляра объекта, тогда он станет слабосвязанным.
Слабая связь - это процесс косвенного предоставления зависимости, в которой нуждается ваш класс, без предоставления всей информации о зависимости (т. Е. В интерфейсе from) в случае, когда вы напрямую указываете на зависимость, которая не является хорошим способом кодирования.
Слабое связывание является ответом на жестко закодированные зависимости старого стиля и связанные с этим проблемы, такие как частая перекомпиляция, когда что-то меняется, и повторное использование кода. Он делает упор на реализации рабочей логики в компонентах и избегает связывания кода для конкретного решения.
Слабая связь = IoC Смотрите это для более легкого объяснения.
Тесная связь означает, что классы и объекты зависят друг от друга. В общем, сильное связывание обычно нехорошо, поскольку оно снижает гибкость и возможность повторного использования кода, в то время как слабое связывание означает уменьшение зависимостей класса, который напрямую использует другой класс.
Тесная связь Сильно связанный объект - это объект, который должен знать о других объектах и обычно сильно зависит от интерфейсов друг друга. Изменение одного объекта в сильно связанном приложении часто требует изменения ряда других объектов. В небольших приложениях мы можем легко идентифицировать изменения, и меньше шансов что-то пропустить. Но в больших приложениях эти взаимозависимости не всегда известны каждому программисту, и есть шанс пропустить изменения. Пример:
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());
}
}
В приведенном выше примере код, который определяется такой реализацией, использует слабую связь и рекомендуется, поскольку класс B должен пройти через класс A, чтобы получить свое состояние, в котором применяются правила. Если класс A изменяется внутри, класс B не сломается, поскольку он использует только класс A в качестве способа связи.
Output
getA() method
aObject value is: 0
Если создание / существование объекта зависит от другого объекта, который не может быть адаптирован, его тесная связь. И, если зависимость может быть адаптирована, ее слабая связь. Рассмотрим пример на Java:
class Car {
private Engine engine = new Engine( "X_COMPANY" ); // this car is being created with "X_COMPANY" engine
// Other parts
public Car() {
// implemenation
}
}
Клиент Car
класс может создать его только с движком "X_COMPANY".
Подумайте о том, чтобы разорвать эту связь с возможностью изменить это
class Car {
private Engine engine;
// Other members
public Car( Engine engine ) { // this car can be created with any Engine type
this.engine = engine;
}
}
Теперь Car
не зависит от механизма "X_COMPANY", так как он может быть создан с типами.
Примечание, специфичное для Java: использование интерфейсов Java только для разделения не является подходящим подходом. В Java у интерфейса есть цель - действовать как контракт, который по сути обеспечивает поведение / преимущество разъединения.
Комментарий Билла Росмуса в принятом ответе имеет хорошее объяснение.
Слабая и тесная связь — это зависимость одного компонента программы от другого. Это означает зависимость не только от класса программирования, но и от компонентов системы программирования вообще.
Например, если вы используете только простой необработанный SQL-запрос для получения данных от SQL Server, это слабая связь. Противоположностью слабой связи и простого необработанного SQL-запроса является жесткая связь и ядро Entity Framework. В Entity Framework Core вы должны использовать полную модель с классом POCO в своем коде, отражающую структуру базы данных, что означает, что любые изменения в базе данных вы должны отразить в коде.
Итак, Tight Coupling между программным кодом и структурой базы данных — это Entity Framework, противоположностью этому подходу является отказ от использования любых ORM и отказ от полных зеркальных структур базы данных в вашем программном коде.