четвер, 13 лютого 2020 р.

Adapter pattern

Вирізка із книги "GoF Design Patterns - with examples using Java and UML2" by: Benneth Christiansson (Ed.) Mattias Forss, Ivar Hagen, Kent Hansson, Johan Jonasson, Mattias Jonasson, Fredrik Lott, Sara Olsson, and Thomas Rosevall. License: Creative Commons Attribution-ShareAlike 3.0 License.

Визначення

Патерн адаптер(Adapter) або ж обгортка (Wrapper) використовується для трансляції інтерфейсу одного класу в інтерфейс іншого. Це означає, що ми можемо зробити так, щоб класи працювали разом, хоча вони мають несумісні інтерфейси. Клас адаптер використовує множинне успадкування (розширяючи один клас і/або реалізуючи один або більше класів), щоб адаптувати один інтерфейс до іншого. Об’єкт адаптер покладається на агрегацію об’єктів.

Де використовується
  • Коли ви хочети використовувати існуючий клас, але його інтерфейс не зіставляється з тим який вам потрібен
  • Коли ви хочете створити повторно використовуваний клас, що взаємодії з непов’язаними або невідомими наперед класами, що є класами, що необов’язково мають сумісний інтерфейс.
  • Коли ви хочете збільшити прозорість класів
  • Коли ви хочете створити вбудовуваний набір.

Переваги
  • Висока повторна використовуваність класів
  • Вводиться лише один клас
Недоліки/наслідки
  • При використанні Java, об’єкт ціль (Target) має бути інтерфейсом.
Структура
На діаграмі вище:
  • Клас Client очікує певний інтерфейс (що зветься цільовим інтерфейсом (Target interface))
  • Наявний інтерфейс класу не співпадає з інтерфейсом Target
  • Клас Adapter долає неспівпадіння між інтерфейсом Target та наявним інтерфейсом
  • Наявний інтерфейс названо Adaptee
Маленький приклад

Уявімо вам необхідно розробити простий файловий менеджер для обробки техстових документів. Наявний існуючий ресурс, що вже обробляє їх і по деяким причинам ви змушені використовувати визначений інтерфейс для вашого файлового менеджера. Використовуючи клас адаптер ми можемо використати інтерфейс, що вимагається, із збереженням існуючої функціональності. На діаграмі класів нижче інтерфейс FileManager є цільовим (бажаним інтерфейсом). FileManagerUtil – це існуючий клас, який потрібно використати і який ми б хотіли адаптувати до інтерфейсу FilManager. Адаптацію здійснюємо в класі FileManagerImpl. Цей клас застосовує бажаний інтерфейс і існуючу функціональність через успадкування і є класом адаптером.


public interface FileManager {
 public String open(String s);
 public String close();
 public String read(int pos, int amount, byte[] data);
 public String write(int pos, int amount, byte[] data);
}


import java.util.*;
import java.io.*;

public class FileManagerUtil {
 private RandomAccessFile f;

 public boolean openFile(String fileName) {
  System.out.println("Opening file: " + fileName);
  boolean success = true;
  return success;
 }

 public boolean closeFile() {
  System.out.println("Closing file");
  boolean success = true;
  return success;
 }

 public boolean writeToFile(String d, long pos, long amount) {
  System.out.print("Writing " + amount + " chars from string: " + d);
  System.out.println(" to pos: " + pos + " in file");
  boolean success = true;
  return success;
 }

 public String readFromFile(long pos, long amount) {
  System.out.print("Reading " + amount + " chars from pos: " + pos
    + " in file");
  return new String("dynamite");
 }
}

public class FileManagerImpl extends FileManagerUtil implements FileManager {
 public String close() {
  return new Boolean(closeFile()).toString();
 }

 public String open(String s) {
  return new Boolean(openFile(s)).toString();
 }

 public String read(int pos, int amount, byte[] data) {
  return readFromFile(pos, amount);
 }

 public String write(int pos, int amount, byte[] data) {
  boolean tmp = writeToFile(new String(data), pos, amount);
  return String.valueOf(tmp);
 }
}

public class FileManagerClient {
 public static void main(String[] args) {
  FileManager f = null;
  String dummyData = "dynamite";
  f = new FileManagerImpl();
  System.out.println("Using filemanager: " + f.getClass().toString());
  f.open("dummyfile.dat");
  f.write(0, dummyData.length(), dummyData.getBytes());
  String test = f.read(0, dummyData.length(), dummyData.getBytes());
  System.out.println("Data written and read: " + test);
  f.close();
 }
}
При застосуванні FileManagerClient результатом буде:

c:>Opening file: dummyfile.dat
c:>Writing 8 chars from string: dynamite to pos: 0 in file
c:>Reading 8 chars from pos: 0 in fileData written and read: dynamite
c:>Closing file

Приклади застосування:

В Java API застосовується патерн адаптер у WindowAdapter, ComponentAdapter, ContainerAdapter, FocusAdapter, KeyAdapter, MouseAdapter, MouseMotionAdapter.

Немає коментарів:

Дописати коментар