Зв’язок у ООП: Перспектива Java

pic

Абстрактний приклад тісного з'єднання (зліва) та слабкого з'єднання (справа)

Зв'язок (Coupling) означає ступінь залежності між компонентами/класами і використовується для опису залежностей між класами в додатку. Це дуже важливо для проектування підтримуваної системи.

Є два типи зв'язків.

1. Тісне з'єднання

  1. Як і підказує назва, компоненти тісно з'єднані, тобто сильно залежать один від одного.
  2. Тому зміна одного класу може вимагати змін в іншому класі, що робить систему менш гнучкою.
  3. Один клас зазвичай знає майже все про інший клас.
  4. Можна порівняти це з одруженою парою, де чоловік знає все про свою жінку, а зміна/порушення цього зв'язку — дорого коштує.

Приклад:

Пульт від телевізора Samsung працює тільки з телевізором Samsung.

Тут

  1. Обидва компоненти сильно з'єднані один з одним.
  2. Пульт може виконувати різноманітні функції, такі як керування гучністю, зміна каналів, налаштування, регулювання яскравості тощо.
  3. Однак будь-які зміни в дизайні чи функціональності телевізора потребують відповідних змін в пульті.

Приклад коду

class SamsungTV {  
 int volume = 12;  

 public void showNextChannel(){  
 System.out.println("Switched to next channel");  
 }  

 public void switchToChannel(int channelId){  
 System.out.println("Switched to channel" + channelId);  
 }  

 public void adjustVolume(int delta){  
 volume += delta;  
 volume = Math.max( Math.min(volume, 100), 0 );  
 System.out.println(volume);  
 }  

 public void startBixby(){  
 System.out.println("Voice command enabled");  
 }  
}  

class SamsungRemote{  
 // Тісно з'єднані. Неможливо передати інший тип телевізора  
 public final SamsungTV tv;  

 public SamsungRemote(SamsungTV tv){  
 this.tv = tv;  
 }  

 public void pressNextChannelButton(){  
 tv.showNextChannel();  
 }  

 public void pressIncreaseVolume(){  
 tv.adjustVolume(1);  
 }  
 public void pressDecreaseVolume(){  
 tv.adjustVolume(-1);  
 }  

 public void pressVoiceInput(){  
 tv.startBixby();  
 }  
}  

public class Medium{  
 public static void main(String... args){  
 SamsungTV tv = new SamsungTV();  
 SamsungRemote remote = new SamsungRemote(tv);  

 remote.pressIncreaseVolume(); // 13  
 remote.pressVoiceInput(); // Voice command enabled  
 }  
}

2. Слабке з'єднання

  1. Як і підказує назва, компоненти з'єднані слабо, тобто менше або взагалі не залежать один від одного.
  2. Зміна одного класу не обов'язково впливає на інший клас.
  3. Один клас знає лише ті частини, які інший клас відкриває через інтерфейс.
  4. Можна порівняти це з парою дівчина-хлопець, де хлопець знає тільки те, що його дівчина йому каже/відкриває. І зміна/порушення цього зв'язку майже нічого не коштує.

Приклад

Китайський пульт працює з різними телевізорами

Тут,

  1. Пульт не тісно з'єднаний з певними марками телевізорів.
    2.
    Пульт не може виконувати всі операції, характерні для конкретної марки телевізора, натомість він виконує загальні операції, такі як зміна каналів, регулювання гучності тощо.

Приклад коду

// Загальні функціональності для всіх телевізорів  
interface TV {  
 public void showNextChannel();  
 public void switchToChannel(int channelId);  
 public void adjustVolume(int delta);  
}  

// Один тип телевізора  
class SamsungTV implements TV{  
 int volume = 12;  
 @Override  
 public void showNextChannel(){  
 System.out.println("Switched to next channel");  
 }  
 @Override  
 public void switchToChannel(int channelId){  
 System.out.println("Switched to channel" + channelId);  
 }  
 @Override  
 public void adjustVolume(int delta){  
 volume += delta;  
 volume = Math.max( Math.min(volume, 100), 0 );  
 System.out.println(volume);  
 }  

 public void startBixby(){  
 System.out.println("Voice command enabled");  
 }  
}  

// Інший тип телевізора  
class AppleTV implements TV{  
 int volume = 12;  
 @Override  
 public void showNextChannel(){  
 System.out.println("Switching...");  
 }  
 @Override  
 public void switchToChannel(int channelId){  
 System.out.println(channelId +" switching done");  
 }  
 @Override  
 public void adjustVolume(int delta){  
 volume += delta;  
 if(volume < 0) volume = 0;  
 if(volume > 100) volume = 100;  

 System.out.println("Volume set to "+volume);  
 }  

 public void startCamera(){  
 System.out.println("Camera started");  
 }  
}  

// Загальний пульт  
class ChineseRemote{  
 private TV tv;  

 public ChineseRemote(TV tv){  
 this.tv = tv;  
 }  

 public void pressNextChannelButton(){  
 tv.showNextChannel();  
 }  

 public void pressIncreaseVolume(){  
 tv.adjustVolume(1);  
 }  
 public void pressDecreaseVolume(){  
 tv.adjustVolume(-1);  
 }  
}  


public class Medium {  

 public static void main(String... args){  
 TV samsungTV = new SamsungTV();  
 TV appleTV = new AppleTV();  
 ChineseRemote samsungRemote = new ChineseRemote(samsungTV);  
 ChineseRemote appleRemote = new ChineseRemote(appleTV);  

 samsungRemote.pressIncreaseVolume(); // 13  
 samsungRemote.pressNextChannelButton(); // Switched to next channel  
 System.out.println("-------------------------");  
 appleRemote.pressIncreaseVolume(); // Volume set to 13  
 appleRemote.pressNextChannelButton(); // Switching...  
 }  
}

Зверніть увагу на слабке з'єднання:

  1. Ми не обмежені конкретними марками телевізорів.
  2. Ми можемо легко додавати інші марки телевізорів; потрібно лише реалізувати інтерфейс TV. Решта коду залишиться без змін.
  3. Клас, що реалізує інтерфейс, може мати інші методи, якщо це необхідно.
  4. Таким чином, пульт більше не з'єднаний тісно з будь-яким телевізором.

Повернемося до нашого зображення

pic

Те ж саме зображення, що й раніше

  1. Слабке з'єднання реалізоване через інтерфейс.
  2. Тільки методи, визначені в інтерфейсі, доступні класу A.
  3. Клас A може використовувати будь-який клас телевізора, що реалізує інтерфейс TV, без необхідності змінювати код у класі A.

Якщо у вас є якісь питання чи зауваження щодо пояснення, не соромтеся написати в коментарях.

Перекладено з: Coupling in OOP: A Java Perspective

Leave a Reply

Your email address will not be published. Required fields are marked *