Delegates methods in java

Java Blog

Паттерн делегирования (Delegation) является поведенческим (behavioral) паттерном проектрования.

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

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

Используйте шаблон делегата для достижения следующего:

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

Пример использования паттерна делегирования на Java

Предположим у нас есть автомобиль — интерфейс Car, имеющий метод ride:

package example; public interface Car

Класс CarController реализует интерфейс Car, но сам действие не выполняет, а делегирует это вспомогательному классу, экземпляр которого хранит в своем поле car:

package example; public class CarController implements Car < private final Car car; public CarController(Car car) < this.car = car; >@Override public void ride(String name) < car.ride(name); >; >

Есть вспомогательные классы которые непосредственно выполняют действие — BMWCar, MercedesCar, VolvoCar — они также реализуют интерфейс Car, но в самом приложении вызываются опосредованно через экземпляр класса CarController, который делегирует им выполнение работы:

package example.cars; import example.Car; public class BMWCar implements Car < @Override public void ride(String name) < System.out.println(name + " rides in BMW"); >; >
package example.cars; import example.Car; public class MercedesCar implements Car < @Override public void ride(String name) < System.out.println(name + " rides in Mercedes"); >; >
package example.cars; import example.Car; public class VolvoCar implements Car < @Override public void ride(String name) < System.out.println(name + " rides in Volvo"); >; >

В самом приложении экземпляры вспомогательных классов передаются в CarController и вызов на выполнение действия осуществляется на экземпляре класса CarController:

package example; import example.cars.*; public class App < private static final String RIDER = "Tom"; public static void main(String[] args) < CarController bmw = new CarController(new BMWCar()); CarController mercedes = new CarController(new MercedesCar()); CarController volvo = new CarController(new VolvoCar()); bmw.ride(RIDER); mercedes.ride(RIDER); volvo.ride(RIDER); >>

  • Получить ссылку
  • Facebook
  • Twitter
  • Pinterest
  • Электронная почта
  • Другие приложения

Комментарии

Отправить комментарий

Популярные сообщения из этого блога

Методы класса Object в Java

Изображение

Класс Object является корнем иерархии классов. У каждого класса есть Object как суперкласс. Все объекты, включая массивы, реализуют методы этого класса. Методы класса Object Метод getClass() public final Class getClass() Возвращает класс времени исполнения (runtime class) этого Object. Возвращенный объект Class — это объект, который заблокирован статическими синхронизированными методами представленного класса. Фактический тип результата — Class где |X| заменяется статическим типом выражения, для которого вызывается getClass. Например, в этом фрагменте кода не требуется приведение: Number n = 0; Class c = n.getClass(); Метод getClass() возвращает: Объект Class, представляющий класс времени исполнения (runtime class) этого объекта. Метод hashCode public int hashCode() Возвращает значение хэш-кода для объекта. Этот метод поддерживается для использования хэш-таблиц, таких как те, что предоставляются HashMap. Основной контракт метода hashCo

Как получить текущий timestamp в Java

Изображение

Чтобы получить текущий timestamp в Java : package main; import java.sql.Timestamp; public class Main < public static void main(String[] args)< Timestamp timestamp = new Timestamp(System.currentTimeMillis()); System.out.println(timestamp); >> Вывод: 2019-10-03 10:09:21.61 Вот еще два более подробных примера как получить текущий timestamp в Java: 1. java.sql.Timestamp Есть два метода получить текущий java.sql.Timestamp package main; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Date; public class Main < private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); public static void main(String[] args) < // Метод 1 Timestamp timestamp = new Timestamp(System.currentTimeMillis()); System.out.println(timestamp); // Метод 2 - через Date Date date = new Date(); System.out.println(new Timestamp(date.getTime()

Spring Boot стартеры

Изображение

Стартеры — это набор удобных дескрипторов зависимостей, которые вы можете включить в свое приложение. Вы получаете универсальный набор для всех необходимых вам Spring и связанных с ними технологий без необходимости искать примеры кода и копировать и вставлять множество дескрипторов зависимостей. Например, если вы хотите начать использовать Spring и JPA для доступа к базе данных, включите в ваш проект зависимость spring-boot-starter-data-jpa. Стартеры содержат множество зависимостей, которые необходимы вам для быстрого запуска и запуска проекта с согласованным, поддерживаемым набором управляемых переходных зависимостей. Что указывается в имени стартера Все официальные стартеры следуют аналогичной схеме именования; spring-boot-starter-*, где * это конкретный тип приложения. Эта структура наименования предназначена, чтобы помочь, когда вам нужно найти стартер. Интеграция Maven во многие IDE позволяет вам искать зависимости по имени. Например, если установлен соответствующий плагин Ecl

Источник

1. Overview

It is a technique where an object expresses certain behavior to the outside but in reality delegates responsibility for implementing that behaviour to an associated object.

Applicability

  • Reduce the coupling of methods to their class
  • Components that behave identically, but realize that this situation can change in the future.
  • If you need to use functionality in another class but you do not want to change that functionality then use delegation instead of inheritance.

2. Implementation with Examples

Example 1: Let’s take the Ticket Booking example

interface TravelBooking < public void bookTicket(); >
class TrainBooking implements TravelBooking < @Override public void bookTicket() < System.out.println("Train ticket booked"); > >
class AirBooking implements TravelBooking < @Override public void bookTicket() < System.out.println("Flight ticket booked"); > >

Step 4: TicketBokkingByAgent provides an implementation of TravelBooking. But it delegates actual ticket booking to other classes at runtime using Polymorphism.

class TicketBookingByAgent implements TravelBooking < TravelBooking t; public TicketBookingByAgent(TravelBooking t) < this.t = t; > // Delegation --- Here ticket booking responsibility // is delegated to other class using polymorphism @Override public void bookTicket() < t.bookTicket(); > >
public class DelegationDemonstration < public static void main(String[] args) < // Here TicketBookingByAgent class is internally // delegating train ticket booking responsibility to other class TicketBookingByAgent agent = new TicketBookingByAgent(new TrainBooking()); agent.bookTicket(); agent = new TicketBookingByAgent(new AirBooking()); agent.bookTicket(); > >

Example 2: Printers Implementation Example

In this example, the delegates are CanonPrinter, EpsonPrinter, or HpPrinter they all implement Printer. The PrinterController is a delegator class that also implements Printer.

PrinterController is not responsible for the actual desired action but is actually delegated to a helper class either CanonPrinter, EpsonPrinter, or HpPrinter. The consumer does not have or require knowledge of the actual class carrying out the action, only the container on which they are calling.

Step 1: First create a Printer interface that both the Controller and the Delegate classes will implement.

public interface Printer < void print(final String message); >

Step 2: Specialised Implementation of Printer for a CanonPrinter, in this case, the message to be printed is appended to «Canon Printer: «.

public class CanonPrinter implements Printer < private static final Logger LOGGER = LoggerFactory.getLogger(CanonPrinter.class); @Override public void print(String message) < LOGGER.info("Canon Printer : <>", message); > >

Step 3: Specialized Implementation of Printer for an Epson Printer, in this case, the message to be printed is appended to «Epson Printer: «.

public class EpsonPrinter implements Printer < private static final Logger LOGGER = LoggerFactory.getLogger(EpsonPrinter.class); @Override public void print(String message) < LOGGER.info("Epson Printer : <>", message); > >

Step 4: Specialized Implementation of Printer for an HP Printer, in this case, the message to be printed is appended to «HP Printer: «.

public class HpPrinter implements Printer < private static final Logger LOGGER = LoggerFactory.getLogger(HpPrinter.class); @Override public void print(String message) < LOGGER.info("HP Printer : <>", message); > >
  • when the actual implementation of the Printer class changes the delegation will still be operational
  • the actual benefit is observed when there is more than one implementor and they share a delegation control.
public class PrinterController implements Printer < private final Printer printer; public PrinterController(Printer printer) < this.printer = printer; >@Override public void print(String message) < printer.print(message); >> 
public class App < public static final String MESSAGE_TO_PRINT = "hello world"; /** * Program entry point * * @param args command line args */ public static void main(String[] args) < PrinterController hpPrinterController = new PrinterController(new HpPrinter()); PrinterController canonPrinterController = new PrinterController(new CanonPrinter()); PrinterController epsonPrinterController = new PrinterController(new EpsonPrinter()); hpPrinterController.print(MESSAGE_TO_PRINT); canonPrinterController.print(MESSAGE_TO_PRINT); epsonPrinterController.print(MESSAGE_TO_PRINT); > >

Источник

Easy Java delegates with Lombok

Ever wanted to override a method of an object instance in Java?

Let’s say you want to implement a custom Scheduler hook for Project Reactor. You start with Schedulers.addExecutorServiceDecorator, implement a BiFunction accepting Scheduler ’s instance and ScheduledExecutorService and you need to return another ScheduledExecutorService instance where schedule* methods wrapped with your code.

A straightforward approach would be to create a new class, implement all methods of ScheduledExecutorService interface, and delegate most of them to the instance of ScheduledExecutorService we received as an argument. This pattern is called “Delegation”.

But if you check the interface, you will see that you have to implement 17 methods, while you want to override only 4 of them. Is it not only error-prone, but a lot of boilerplate!
Well, 17 is fairly okay, imagine you have to delegate TransferQueue (36 methods)? No, I’m too lazy and not getting paid for the number of lines I wrote!

Project Lombok to the rescue!

When I hear “Java” and “boilerplate” in one sentence, I usually think of Project Lombok. What I like about it is that you don’t have to change your language/tooling/IDE/buildsystem to remove a lot of boilerplate from your Java code. Definitelly check it if you never did before!

There are many features in Lombok, but we will focus on @Delegate annotation. It looks somewhat like this:

class ExcludesDelegateExample  long counter = 0L; private interface Add  // (2) boolean add(String x); boolean addAll(Collection extends String> x); > @Delegate(excludes=Add.class) // (1) private final CollectionString> collection = new ArrayListString>(); public boolean add(String item)  // (3) counter++; return collection.add(item); > public boolean addAll(Collection extends String> col)  (4) counter += col.size(); return collection.addAll(col); > >

No, wait! This is not the end of the article yet!:)

What we have here?
(1): Here we define @Delegate annotation on top of the field. All methods of the Collection interface will be delegated to this field, except the excludes. It will also add Collection interface to the ExcludesDelegateExample class’ signature.
(2): This interface defines which methods Lombok should not delegate. You will have to implement them, otherwise you get a compilation error.
(3): Our custom add method increments a counter before calling the original method.

Not bad, huh? I could end the article here, but there is one trick I use to avoid writing interfaces for the excludes property.

Override it!

While excludes work for simple examples, I feel uncomfortable having to create another interface, look up for the methods, copy them into it, etc…
Maybe one day Lombok will automatically detect implemented methods. Until that happens, there is (IMO) a much cleaner approach (unless you feel bad about creating more classes).

First, simply create a dummy delegate, without any exclusions:

@RequiredArgsConstructor class DelegatingScheduledExecutorService implements ScheduledExecutorService  @Delegate private final ScheduledExecutorService delegate; >

Now we can use this class to override any method we want, with Java’s standard method overriding:

class WrappingScheduledExecutorService extends DelegatingScheduledExecutorService  public WrappingScheduledExecutorService(ScheduledExecutorService delegate)  super(delegate); > @Override public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit)  command = wrap(command); return super.schedule(command, delay, unit); > >

Another good thing about this approach is that you can reuse DelegatingScheduledExecutorService in case you have multiple versions of such delegate.

Источник

Читайте также:  Space in print java
Оцените статью