Поймите «Шаблон декоратора» на примере реального мира - PullRequest
157 голосов
/ 25 апреля 2010

Я изучал Шаблон декоратора , как описано в GOF .

Пожалуйста, помогите мне понять Шаблон декоратора . Может ли кто-нибудь привести пример использования того, где это полезно в реальном мире?

Ответы [ 14 ]

1 голос
/ 08 августа 2014

В Википедии есть пример оформления окна с полосой прокрутки:

http://en.wikipedia.org/wiki/Decorator_pattern

Вот еще один очень «реальный» пример «члена команды, руководителя и менеджера», который показывает, что шаблон декоратора незаменим при простом наследовании:

https://zishanbilal.wordpress.com/2011/04/28/design-patterns-by-examples-decorator-pattern/

0 голосов
/ 06 мая 2019

Давайте возьмем пример PubG. Штурмовые винтовки лучше всего работают с 4-кратным зумом, и пока мы на нем, нам также понадобятся компенсатор и подавитель. Это уменьшит отдачу и уменьшит звук стрельбы, а также эхо. Нам нужно будет реализовать эту функцию, где мы позволим игрокам покупать их любимые ружья и аксессуары. Игроки могут купить пистолет или часть аксессуара или весь аксессуар, и с них будет взиматься соответствующая плата.

Давайте посмотрим, как шаблон декоратора применяется здесь:

Предположим, кто-то хочет купить SCAR-L со всеми тремя аксессуарами, упомянутыми выше.

  1. Возьмите предмет SCAR-L
  2. Украсьте (или добавьте) СКАР-Л с помощью 4-кратного зума
  3. Украсить СКАР-Л объектом-подавителем
  4. Украсить СКАР-Л объектом компрессора
  5. Вызовите метод стоимости и позвольте каждому делегату объекта добавить стоимость используя метод стоимости аксессуаров

Это приведет к диаграмме классов, подобной этой:

Decorator pattern at work

Теперь у нас могут быть такие классы:

public abstract class Gun {     
    private Double cost;    
    public Double getCost() {           
        return cost;        
       }    
    }

public abstract class GunAccessories extends Gun {  }

public class Scarl extends Gun {    
    public Scarl() {            
        cost = 100;
        }   
     }

public class Suppressor extends GunAccessories {        
    Gun gun;        
    public Suppressor(Gun gun) {            
    cost = 5;           
    this.gun = gun;     
    }               
    public double getCost(){            
        return cost + gun.getCost();
    }
}

public class GunShop{   
    public static void main(String args[]){         
    Gun scarl = new Scarl();                
    scarl = new Supressor(scarl);
    System.out.println("Price is "+scarl.getCost());
    }      
}

Мы также можем добавить другие аксессуары и украсить наш пистолет.

Справка:

https://nulpointerexception.com/2019/05/05/a-beginner-guide-to-decorator-pattern/

0 голосов
/ 14 марта 2019

Некоторое время назад я реорганизовал кодовую базу в использование шаблона Decorator, поэтому я попытаюсь объяснить пример использования.

Предположим, у нас есть набор служб, и в зависимости от того, приобрел ли пользователь лицензию на конкретную услугу, нам нужно запустить службу.

Все сервисы имеют общий интерфейс

interface Service {
  String serviceId();
  void init() throws Exception;
  void start() throws Exception;
  void stop() throws Exception;
}

Предварительный рефакторинг

abstract class ServiceSupport implements Service {
  public ServiceSupport(String serviceId, LicenseManager licenseManager) {
    // assign instance variables
  }

  @Override
  public void init() throws Exception {
    if (!licenseManager.isLicenseValid(serviceId)) {
       throw new Exception("License not valid for service");
    }
    // Service initialization logic
  }
}

Если вы внимательно наблюдаете, ServiceSupport зависит от LicenseManager. Но почему это должно зависеть от LicenseManager? Что делать, если нам нужен фоновый сервис, который не должен проверять информацию о лицензии. В сложившейся ситуации нам придется как-то обучить LicenseManager возвращать true для фоновых услуг. Этот подход мне не показался удачным. По моему мнению, проверка лицензии и другая логика были ортогональны друг другу.

Итак Pattern Decorator приходит на помощь и здесь начинает рефакторинг с TDD.

Рефакторинг

class LicensedService implements Service {
  private Service service;
  public LicensedService(LicenseManager licenseManager, Service service) {
    this.service = service;
  }

  @Override
  public void init() {
    if (!licenseManager.isLicenseValid(service.serviceId())) {
      throw new Exception("License is invalid for service " + service.serviceId());
    }
    // Delegate init to decorated service
    service.init();
  }

  // override other methods according to requirement
}

// Not concerned with licensing any more :)
abstract class ServiceSupport implements Service {
  public ServiceSupport(String serviceId) {
    // assign variables
  }

  @Override
  public void init() {
    // Service initialization logic
  }
}

// The services which need license protection can be decorated with a Licensed service
Service aLicensedService = new LicensedService(new Service1("Service1"), licenseManager);
// Services which don't need license can be created without one and there is no need to pass license related information
Service aBackgroundService = new BackgroundService1("BG-1");

Takeaways

  • Сплоченность кода стала лучше
  • Модульное тестирование стало проще, поскольку при тестировании ServiceSupport не нужно имитировать лицензирование
  • Не нужно обходить лицензирование какими-либо специальными проверками для фоновых услуг
  • Правильное разделение обязанностей
0 голосов
/ 30 октября 2015

Шаблон оформления декоратора : Этот шаблон помогает изменить характеристики объекта во время выполнения. Он обеспечивает объектам разные вкусы и дает возможность выбирать, какие ингредиенты мы хотим использовать в этом аромате.

Пример из реальной жизни: Допустим, у вас есть основное место в салоне самолета. Теперь вам разрешено выбирать несколько удобств с места. Каждое удобство имеет свою цену, связанную с этим. Теперь, если пользователь выберет Wi-Fi и премиум-питание, с него будет взиматься плата за место + Wi-Fi + премиум-питание.

enter image description here

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

...