Я осуществил бы рефакторинг код в цикле и затем сделал бы
if( ref $results eq 'ARRAY' ){
my_sub($result) for my $result (@$results);
}else{
my_sub($results);
}
, Конечно, я только сделал бы это, если бы код в цикле был нетривиален.
Шаблон декоратора часто используется с потоками: вы можете обернуть поток потоком, чтобы получить дополнительную функциональность. Я видел это в среде .Net - насколько мне известно, это происходит где-то еще. Мне больше всего нравится использовать GZipStream вокруг FileStream для дополнительного сжатия.
Шаблон декоратора используется для добавления дополнительных функций к конкретному объекту, а не к классу объектов. Легко добавить функциональность ко всему классу объектов путем создания подкласса объекта, но невозможно расширить таким образом отдельный объект. С помощью шаблона декоратора вы можете добавить функциональность к одному объекту и оставить другие, как он, неизменными.
В Java классическим примером шаблона декоратора является реализация Java I / O Streams.
FileReader frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);
Предыдущий код создает объект читатель - lrdr
- который читает из файла и отслеживает номера строк. В строке 1 создается программа чтения файлов ( frdr
), а в строке 2 добавляется отслеживание номеров строк.
На самом деле, я настоятельно рекомендую вам взглянуть на исходный код Java для классов ввода-вывода Java.
Недавно я использовал шаблон декоратора в веб-службе, которая использует следующий интерфейс CommandProcessor:
public Command receive(Request request);
public Response execute(Command command);
public void respond(Response response);
В основном CommandProcessor получает запрос и создает правильную команду, выполняет команду и создает соответствующий ответ и отправляет ответ. Когда я хотел добавить время и регистрировать его, я создал TimerDecorator, который использовал существующий CommandProcessor в качестве своего компонента. TimerDecorator реализует интерфейс CommandProcessor, но просто добавляет время, а затем вызывает свою цель, которая является настоящим CommandProcessor. Примерно так:
public class TimerDecorator implements CommandProcessor {
private CommandProcessor target;
private Timer timer;
public TimerDecorator(CommandProcessor processor) {
this.target = processor;
this.timer = new Timer();
}
public Command receive(Request request) {
this.timer.start();
return this.target.receive(request);
}
public Response execute(Command command) {
return this.target.execute(command);
}
public void respond(Response response) {
this.target.response(response);
this.timer.stop();
// log timer
}
}
Итак, настоящий CommandProcessor заключен внутри TimerDecorator, и я могу обращаться с TimerDecorator так же, как с целевым CommandProcessor, но теперь была добавлена логика синхронизации.
Zend Framework использует декоратор для элементов формы
Дополнительная информация: http://framework.zend.com/manual/en/zend.form.decorators.html
The decorator is simple yet extremely powerful. It is key in achieving separation of concerns and is an essential tool for the Open Closed Principle. Take a common example of placing an order for a product:
IOrderGateway
{
void PlaceOrder(Order order);
{
Main implementation: AmazonAffiliateOrderGateway
Possible decorators could be:
IncrementPerformanceCounterOrderGateway
QueueOrderForLaterOnTimeoutOrderGateway
EmailOnExceptionOrderGateway
InterceptTestOrderAndLogOrderGateway
A more detailed example from here illustrates a decorator that saves contacts for orders that were created using a gift card while completing the order:
class OrderWithGiftCardGateway extends OrderGatewayDecorator { ... public function createOrder(CreateOrderRequest $order) { if ($this->containsGiftCard($order)) { $this->addContactToFolder($order); } return parent::createOrder($order); } }