Где мы должны использовать Template Method - pattern? - PullRequest
7 голосов
/ 12 октября 2009

Может кто-нибудь дать мне пример некоторых ситуаций, когда следует использовать Template Method - pattern?

Дайте мне немного реального использования из вашего собственного опыта.

(До сих пор я нашел это полезным только для отображения данных в слое DA. Извините !!!)

Ответы [ 8 ]

8 голосов
/ 12 октября 2009

A Шаблон шаблона шаблона предоставляет каркас для выполнения любого вида алгоритма или операции и позволяет подклассам переопределять часть логики.

Плюсы: естественное соответствие для построения фреймворков, так что родительские классы фреймворков могут делать обратные вызовы в методы, реализованные в child.

Примеры:

  • java.util.AbstractList
  • Методы doGet и doPost сервлета
  • Метод onMessage MDB
  • Класс действий Struts
  • Классы доступа к данным Spring

Минусы: ограничивает вас одним наследованием в Java.

6 голосов
/ 15 февраля 2010

Применение шаблона Template Method имеет две основные характеристики:

  1. Существует базовый класс (в Java один только с конструкторами protected и, необязательно, объявленный как abstract), который будет разделен на подклассы в клиентском коде.
  2. В базовом классе определены две группы методов : a) один или несколько шаблонных методов (обычно только один) и одна или несколько примитивная операция методы (как правило, более одного). Каждый метод шаблона представляет собой операцию высокого уровня, реализованную в самом базовом классе в терминах примитивных операций, которые предназначены для реализации / переопределения в каждом конкретном подклассе. Обычно шаблонный метод является общедоступным и не может быть переопределен (final, в Java); его документация API должна точно указывать, какие примитивные методы работы он вызывает и когда (то есть он должен описывать «алгоритм»). Метод примитивной операции, представляющий шаг в алгоритме, должен быть закрытым, но переопределяемым (protected, в Java) и может быть двух типов: a) абстрактный метод, который должен быть реализовано в подклассе; б) метод с реализацией по умолчанию / пустым, который может быть переопределен в подклассе.

Одним хорошим примером в Java 6 SDK является метод execute() класса javax.swing.SwingWorker (это метод public final void). В этом случае примитивные методы работы: doInBackground(), process(List) и done(). Первый является абстрактным и поэтому требует реализации в подклассе; он вызывается методом шаблона в фоновом потоке. Два других имеют пустые реализации и могут быть переопределены в подклассе; они вызываются во время и в конце обработки, соответственно, в EDT (потоке диспетчеризации событий Swing), чтобы разрешить обновления пользовательского интерфейса.

По своему опыту я иногда использовал этот шаблон. Одним из таких случаев был базовый класс Java, реализующий интерфейс java.util.Iterator, где next() являлся методом шаблона, и был только один метод примитивной операции, отвечающий за создание экземпляра определенного класса сущности домена (это предназначалось для использования при итерации по список постоянных объектов сущностей домена, использующих JDBC). Лучшим примером в том же приложении был базовый класс, в котором в шаблонном методе реализован многошаговый алгоритм, предназначенный для заполнения «экрана обслуживания бизнес-объектов» (с использованием Swing) из заданного списка постоянных объектов; методы примитивных операций были вызваны для 1) очистки текущего состояния экрана и 2) добавления объекта в табличное представление внутри экрана; необязательно, другие примитивные операции вызывались из метода шаблона, если экран был редактируемым.

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

3 голосов
/ 13 декабря 2011

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

Я подал заявку в одну из программ генерации документов.

public abstract DocumentGenerator() 
{
   generateHeader();
   generateBody();
   generateDetails();
}
public HTMLDocGenerator : DocumentGenerator()
{
   public override generateBody()
   {
     //generate as in html format
   }
}

Вы можете иметь различную реализацию, например, генератор PDF CSV генератор, и значение здесь в том, что они соответствуют алгоритму (генерировать -> заголовок, тело, детали).

2 голосов
/ 10 сентября 2017

Я попытался дать вам несколько реальных примеров и некоторые распространенные ситуации, в которых следует использовать шаблонный метод.

  • Когда вы хотите, чтобы ваша программа была «Открыта для расширения», а также «Закрыта для изменения». Это означает, что поведение модуля может быть расширено, так что мы можем сделать модуль вести себя по-новому и по-разному при изменении требований приложения или для удовлетворения потребностей новых приложений. Однако исходный код такого модуля является неприкосновенным. Никому не разрешено вносить в него изменения в исходном коде. В следующем примере , вы можете добавить новый способ расчета заработной платы (например, дистанционный класс) без изменения предыдущих кодов.

    public abstract class Salary {
    
       public final void calculate() {
            System.out.println("First shared tasks is done.");
            getBaseSalary();
            System.out.println("Second shared tasks is done.");
       }
    
       public abstract void getBaseSalary();
    
    }
    
    public class Hourly extends Salary {
    
        @Override
        public void getBaseSalary() {
            System.out.println("Special Task is done.");
        }
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Salary salary = ....
            salary.calculate();
        }
    }
    
  • Когда вы сталкиваетесь с множеством одинаковых строк кода, которые дублируются путем отсрочки всего лишь нескольких шагов вашего алгоритма. Когда вы реализуете содержимое метода или функции, вы можете найти какой-то раздел вашего кода которые варьируются от одного типа к другому типу. Особенностью этих разделов является то, что можно переопределить или изменить эти разделы метода или функции без изменения основной структуры алгоритма (метода или функции). Например, если вы хотите решить эту проблему без этого шаблона, вы столкнетесь с этим примером:

function0: function1: ... functionN:

1       1               1
2       2               2
...     ...             ...
5       6               n
3       3               3
4       4               4
...     ...             ...

Как видите, разделы 5, 6, n различаются и варьируются от одной функции к другой, однако у вас есть общие разделы, такие как 1,2,3,4, которые дублируются. Давайте рассмотрим решение с одной из известных библиотек Java.

public abstract class InputStream implements Closeable {

    public abstract int read() throws IOException;

    public int read(byte b[], int off, int len) throws IOException {
        ....

        int c = read();
        ....
    }

    ....

}

public class ByteArrayInputStream extends InputStream {  

    ...

    public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
        }
    ...
}
  • Когда вы, как разработчик фреймворка, хотите, чтобы ваши клиенты просто использовали любой исполняемый код, передаваемый в качестве аргумента вашей фреймворке, который должен вызывать (выполнять) этот аргумент в данное время. Это выполнение может быть немедленным, как при синхронном обратном вызове, или может произойти позднее, как при асинхронном обратном вызове. Давайте рассмотрим один из известных.

    public abstract class HttpServlet extends GenericServlet 
        implements java.io.Serializable  {
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
            ...
        }
    
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
            ....
            doGet(req, resp);
            ...
        }
        ...
    }
    }
    
    public class MyServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    
                //do something
            ...
        }
        ...
    }
    
2 голосов
/ 01 мая 2015

Я нарисую один пример из реальной жизни, где я использовал несколько шаблонных методов.

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

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

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

2 голосов
/ 13 мая 2014

Шаблон шаблона следует использовать, когда существует алгоритм со многими реализациями. Алгоритм определен в функции в базовом классе, а реализация выполняется базовым классом и подклассами. Подробное объяснение с примером в реальном времени приведено в http://preciselyconcise.com/design_patterns/templatemethod.php

1 голос
/ 18 января 2017

Метод Template определяет каркасную структуру алгоритма, но откладывает определенные шаги и детали для подклассов. Структура и Поток алгоритма остается статичным, но детали шагов отложено до подклассов.

Я использовал Template Method Pattern для подготовки содержимого документа. Было много разных видов документов, каждый из которых имеет свои небольшие модификации. Однако основной процесс подготовки документов был одинаковым для всех.

1 голос
/ 12 октября 2009

Я использовал метод шаблона для бизнес-логики, в котором несколько компонентов использовали один и тот же процесс, но реализация была немного другой.

...