1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
16.5 抽象的应用.md 9.3 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

Применение абстракций

Дойдя до этого этапа, следует рассмотреть оставшиеся части паттерна проектирования — где использовать классы? Поскольку метод классификации отходов в корзину является крайне неприятным и слишком прямолинейным подходом, почему бы не изолировать этот процесс, скрыв его внутри одного класса? Это известная рекомендация "если вы должны делать что-то неприятное, то хотя бы локализуйте это в одном классе". Внешний вид такого решения может выглядеть следующим образом:

Теперь, при добавлении нового типа Trash, инициализация объекта TrashSorter должна будет меняться. Можно представить себе, что класс TrashSorter будет иметь следующий вид:

class TrashSorter extends Vector {
    void sort(Trash t) { /* ... */ }
}

То есть, TrashSorter представляет собой последовательность ссылок на Vector, который сам содержит ссылки на Trash. Для установки новых значений TrashSorter можно использовать метод addElement(), как показано ниже:

TrashSorter ts = new TrashSorter();
ts.addElement(new Vector());
```Однако теперь метод `sort()` становится проблемой. Как метод, закодированный статически, он должен реагировать на добавление нового типа. Чтобы решить эту проблему, необходимо удалить информацию о типах из метода `sort()`, сделав так, чтобы он вызывал универсальный метод, который заботился бы обо всех деталях работы с типами. Это, конечно, ещё один способ описать динамическое связывание метода. Таким образом, метод `sort()` просто будет проходить по последовательности и вызывать динамический метод для каждого `Vector`. Так как задача этого метода состоит в том, чтобы собирать интересующие его отходы, его можно назвать `grab(Trash)`. Структура теперь выглядит следующим образом:![](16-2.gif)Где каждый `TrashSorter` должен вызвать метод `grab()`. В зависимости от типа, содержащегося в текущем `Vector`, будут получены различные результаты. То есть, `Vector` должен знать, какой тип он содержит. Традиционный способ решения этой проблемы  создать базовый класс "Trash bin" (корзина для отходов) и наследовать новый производный класс для каждого уникального типа. Если Java имела бы механизм параметризованных типов, это было бы самым простым решением. Однако для таких классов мы не хотели бы выполнять сложную ручную работу; будущее "наблюдение" предоставляет лучший способ кодирования. Основной принцип ООП гласит, что "для изменения состояния используйте данные члены, а для изменения поведения — полиморфизм". В случае с `Vector<Paper>` (вектор бумаги) и `Vector<Glass>` (вектор стекла), вы можете подумать, что методы `grab()` для каждого типа наверняка будут иметь различное поведение. Однако это будет зависеть от типа, а не от чего-либо ещё. Это можно рассматривать как различные состояния, и поскольку Java имеет класс для представления типов (`Class`), его можно использовать для определения того, какой тип `Trash` содержится в конкретном `Tbin`. Для `Tbin` требуется конструктор, который принимает выбранный нами `Class`. Это позволяет сообщить `Vector`, какой тип данных он будет содержать.Затем метод `grab()` использует класс `BinType` и RTTI для проверки, соответствует ли переданный ему объект `Trash` тому типу, который он должен собирать.Ниже приведено полное решение. Нумерованные закомментированные строки (например, *1*) помогают связать программный код с последующими объяснениями.

```java
//: RecycleB.java
// Добавление более сложных объектов в задачу по управлению отходами
package c16.recycleb;
import c16.trash.*;
import java.util.*;

// Вектор, который допускает только правильный тип:
class Tbin extends Vector {
  Class binType;
  Tbin(Class binType) {
    this.binType = binType;
  }
  boolean grab(Trash t) {
    // Сравнение типов классов:
    if(t.getClass().equals(binType)) {
      addElement(t);
      return true; // Объект захвачен
    }
    return false; // Объект не захвачен
  }
}

class TbinList extends Vector { //(*1*)
  boolean sort(Trash t) {
    Enumeration e = elements();
    while(e.hasMoreElements()) {
      Tbin bin = (Tbin)e.nextElement();
      if(bin.grab(t)) return true;
    }
    return false; // Контейнер для t не найден
  }
  void sortBin(Tbin bin) { // (*2*)
    Enumeration e = bin.elements();
    while(e.hasMoreElements())
      if(!sort((Trash)e.nextElement()))
        System.out.println("Контейнер не найден");
  }
}

public class RecycleB {
  static Tbin bin = new Tbin(Trash.class);
  public static void main(String[] args) {
    // Заполнение контейнера для отходов:
    ParseTrash.fillBin("Trash.dat", bin);

    TbinList trashBins = new TbinList();
    trashBins.addElement(new Tbin(Aluminum.class));
    trashBins.addElement(new Tbin(Paper.class));
    trashBins.addElement(new Tbin(Glass.class));
    // Добавьте одну строчку здесь: (*3*)
    trashBins.addElement(new Tbin(Cardboard.class));

    trashBins.sortBin(bin); // (*4*)

    Enumeration e = trashBins.elements();
    while(e.hasMoreElements()) {
      Tbin b = (Tbin)e.nextElement();
      Trash.sumValue(b);
    }
    Trash.sumValue(bin);
  }
} ///:~
```(1) Класс `TbinList` хранит список ссылок на объекты типа `Tbin`, поэтому метод `sort()` может использовать наследование от `Tbin` при поиске совпадений с переданным объектом `Trash`. Функция `sortBin()` позволяет передать полный объект `Tbin`, и она будет проходить по нему, отсеивая каждый тип `Trash` и сортируя его в определённый `Tbin`. Обратите внимание на универсальность этих кодов: при добавлении нового типа данных изменениям самой системы не подлежит. Когда новому типу данных или другим событиям требуется минимальное количество изменений в существующих кодах, это указывает на то, что система была спроектирована таким образом, чтобы легко расширяться. (3) Теперь вы можете оценить, насколько легко добавлять новые типы. Для поддержки добавления требуется внести изменения лишь в несколько строк кода. При необходимости можно даже улучшить дизайн, чтобы большее количество кода оставалось "неизменным".(4) Вызов метода позволяет отсортировать содержимое `bin` в соответствующие контейнеры для каждого типа отходов.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master