Рубрики
Без рубрики

Шаблоны проектирования: Шаблон наблюдателя

первоначально опубликовано в моем блоге на henricodesjava.blog Всем привет! Глава вторая в разделе “Дизайн головы”… Помеченный шаблонами, java, дизайном.

первоначально опубликовано в моем блоге по адресу первоначально опубликовано в моем блоге по адресу

Всем привет! Глава вторая в Шаблоны проектирования Head First: Руководство для мозга все о шаблоне наблюдателя. Они отмечают, насколько фундаментально и часто используется этот шаблон. А также намекнуть на идею о том, что будущие паттерны в этой книге основаны на этой и других комбинациях паттернов. Итак, давайте поговорим о шаблоне Наблюдателя.

Проблема, которую пытается решить этот шаблон, связана с коммуникацией и управлением. Простой абстрактный пример, приведенный в тексте, касается газетной издательской компании и ее подписчиков. Технически эти отношения можно классифицировать как отношения “ОДИН КО МНОГИМ”, “один издатель” и “много подписчиков”. В тексте используется термин ” Тема ” для обозначения издателя, а термин ” Наблюдатель ‘ для обозначения подписчиков.

Далее я приведу более конкретный пример. Я буду использовать пример, немного отличающийся от текста, чтобы помочь проиллюстрировать эту идею. Допустим, мы финансовый стартап, и у нас есть идея приложения для умных часов, которое может взаимодействовать со всеми вашими финансовыми учреждениями, чтобы дать вам представление о ваших финансах с высоты птичьего полета. Например, он может показать вам остатки на вашем текущем счете или цены на акции, которыми вы владеете. У нас есть доступ к классу, который может возвращать эти значения для нас, давайте назовем этот класс FinancialData . Для целей этого примера нам все равно, как он извлекает эту информацию.

Ниже приведена наивная реализация нашего приложения для смарт-часов вместе с объяснением. Конечно, все это просто псевдокод, никакого реального кода умных часов.

В этой реализации есть несколько недостатков. Во-первых, мы нарушаем принцип проектирования, изложенный в первой главе. _ Определите аспекты вашего приложения, которые различаются, и отделите их от того, что остается неизменным.  _ Линии с зелеными стрелками представляют другой экран на часах, и в будущем мы, возможно, захотим добавить больше экранов. Когда это время придет, изменения в этом классе, к сожалению, неизбежны. Строки с красными стрелками извлекают финансовые данные, и хотя это тоже может измениться, это будет изменение, вызванное изменением API, а не изменением нашего кода на стороне клиента. Мы также нарушаем другой принцип проектирования: _программа для интерфейса, а не для реализации.  _ Если бы только был способ, которым мы могли бы аккуратно отделить код, который меняется, от кода, который этого не делает, а также не программировать реализацию? Представляем, шаблон наблюдателя!

Шаблон наблюдателя : Определяет зависимость “один ко многим” между объектами, так что, когда один объект изменяет состояние, все его иждивенцы уведомляются и обновляются автоматически.

Мы добьемся этого и введем слабую связь с помощью интерфейсов. Давайте проиллюстрируем это определение диаграммой классов.

Теперь, используя эти диаграммы классов в качестве руководства, давайте рассмотрим реализацию нашего приложения для смарт-часов. Сначала два интерфейса приведены ниже.

public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}

public interface Observer {
    public void upate(Object obj);
}

Далее давайте взглянем на наш новый класс финансовых данных, который реализует интерфейс Subject.

public class FinancialData implements Subject {
   private ArrayList observers;

   private float checkingBalance;
   private float savingsBalance;

   private float stockValue;
   private float fourOnekValue;

   private float weekSpending;
   private float monthSpending;

   public FinancialData(){
      observers = new ArrayList();
   }

   public void registerObserver(Observer o){
      observers.add(o);
   }

   public void removeObserver(o){
      int i = observers.indexOf(o);
      if(i > 0){
         observers.remove(i);
      }
   }

   public void notifyObservers(){
      for(int i = 0; i

Теперь давайте взглянем на одного из наших наблюдателей – экран смарт-часов Balance.

public class BalanceScreen implements Observer {
   private float checkingBal;
   private float savingsBal;
   private Subject financialData;

   public BalanceScreen(Subject financialData){
      this.financialData = financialData;
      financialData.registerObserver(this);
   }

   public void update(Object obj){
      if( obj instanceof FinancialData){
         FinancialData fd = (FinancialData) obj;
         this.checkingBal = fd.getCheckingBalance();
         this.savingsBal = fd.getSavingsBalance();
      }
      display();
   }
   // other BalanceScreen methods here
}

Наконец, давайте взглянем на программу, чтобы склеить все это вместе.

public class SmartWatch {
    public static void main(String[] args){
        FinancialData financialData = new FinancialData();

        BalanceScreen balanceScreen = new BalanceScreen(financialData);
        InvestmentScreen investmentScreen = new InvestmentScreen(financialData);
        SpendingScreen spendingScreen = new SpendingScreen(financialData);

        // not using an actualy finance api, so we set values manually
        financialData.setNewBalanceData(348.12, 3600.87);
        financialData.setNewInvestmentData(899.12, 45000.65);
        financialData.setNewSpendingData(210.34, 677.45);

        // at this point we should see print statements for all 3 screens
    }
}

Вот оно у вас! Мы внедрили интерфейсы и создали некоторый код для его тестирования. Теперь, пожалуйста, обратите внимание, что на самом деле я не запустил этот код, поэтому в этих строках может быть одна или две ошибки. Для будущего поста мне придется создать проект и разместить этот рабочий код на github. Спасибо за чтение! Ре'”рЕ½

(первоначально опубликовано в моем личном блоге: https://henricodesjava.blog )

Оригинал: “https://dev.to/henriavo/design-patterns-observer-pattern-clb”