Абстрактний приклад тісного з'єднання (зліва) та слабкого з'єднання (справа)
Зв'язок (Coupling) означає ступінь залежності між компонентами/класами і використовується для опису залежностей між класами в додатку. Це дуже важливо для проектування підтримуваної системи.
Є два типи зв'язків.
1. Тісне з'єднання
- Як і підказує назва, компоненти тісно з'єднані, тобто сильно залежать один від одного.
- Тому зміна одного класу може вимагати змін в іншому класі, що робить систему менш гнучкою.
- Один клас зазвичай знає майже все про інший клас.
- Можна порівняти це з одруженою парою, де чоловік знає все про свою жінку, а зміна/порушення цього зв'язку — дорого коштує.
Приклад:
Пульт від телевізора Samsung працює тільки з телевізором Samsung.
Тут
- Обидва компоненти сильно з'єднані один з одним.
- Пульт може виконувати різноманітні функції, такі як керування гучністю, зміна каналів, налаштування, регулювання яскравості тощо.
- Однак будь-які зміни в дизайні чи функціональності телевізора потребують відповідних змін в пульті.
Приклад коду
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. Слабке з'єднання
- Як і підказує назва, компоненти з'єднані слабо, тобто менше або взагалі не залежать один від одного.
- Зміна одного класу не обов'язково впливає на інший клас.
- Один клас знає лише ті частини, які інший клас відкриває через інтерфейс.
- Можна порівняти це з парою дівчина-хлопець, де хлопець знає тільки те, що його дівчина йому каже/відкриває. І зміна/порушення цього зв'язку майже нічого не коштує.
Приклад
Китайський пульт працює з різними телевізорами
Тут,
- Пульт не тісно з'єднаний з певними марками телевізорів.
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...
}
}
Зверніть увагу на слабке з'єднання:
- Ми не обмежені конкретними марками телевізорів.
- Ми можемо легко додавати інші марки телевізорів; потрібно лише реалізувати інтерфейс TV. Решта коду залишиться без змін.
- Клас, що реалізує інтерфейс, може мати інші методи, якщо це необхідно.
- Таким чином, пульт більше не з'єднаний тісно з будь-яким телевізором.
Повернемося до нашого зображення
Те ж саме зображення, що й раніше
- Слабке з'єднання реалізоване через інтерфейс.
- Тільки методи, визначені в інтерфейсі, доступні класу A.
- Клас A може використовувати будь-який клас телевізора, що реалізує інтерфейс TV, без необхідності змінювати код у класі A.
Якщо у вас є якісь питання чи зауваження щодо пояснення, не соромтеся написати в коментарях.
Перекладено з: Coupling in OOP: A Java Perspective