Декоратор (шаблон проектування)

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до: навігація, пошук

Декоратор, Decorator — структурний шаблон проектування, призначений для динамічного підключення додаткових можливостей до об'єкта. Шаблон Decorator надає гнучку альтернативу методу визначення підкласів з метою розширення функціональності.

Основні характеристики[ред.ред. код]

Завдання[ред.ред. код]

Об'єкт, який передбачається використовувати, виконує основні функції. Проте може виникнути потреба додати до нього деяку додаткову функціональність, яка виконуватиметься до або після основної функціональності об'єкта.

Спосіб вирішення[ред.ред. код]

Декоратор передбачає розширення функціональності об'єкта без визначення підкласів.

Учасники[ред.ред. код]

Клас ConcreteComponent — клас, в який за допомогою шаблону Декоратор додається нова функціональність. В деяких випадках базова функціональність надається класами, похідними від класу ConcreteComponent. У подібних випадках клас ConcreteComponent є вже не конкретним, а абстрактним. Абстрактний клас Component визначає інтерфейс для використання всіх цих класів.

Наслідки[ред.ред. код]

Функціональність, що додається, реалізується в невеликих об'єктах. Перевага полягає в можливості динамічно додавати цю функціональність до або після основної функціональності об'єкта ConcreteComponent.

Реалізація[ред.ред. код]

Створюється абстрактний клас, що представляє як початковий клас, так і нові функції, що додаються в клас. У класах-декораторах нові функції викликаються в необхідній послідовності — до або після виклику подальшого об'єкта.

Приклад на Java[ред.ред. код]

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
 
abstract class WordSplitter {
    abstract public List<String> getWords(String wordString);
}
 
/**
Просто перетворює рядок слів, написаних через пробіл, на список слів
*/
class PureWordSplitter extends WordSplitter {
 
    public PureWordSplitter() {}
 
    public List<String> getWords(String wordString) {
        String[] wordArray = wordString.split(" ");
        List<String> wordList = new ArrayList<String>(wordArray.length);
	Collections.addAll(wordList, wordArray);
        return wordList;
    }
}
 
/**
Абстрактний клас для декораторів
*/
abstract class FilteringSplitter extends WordSplitter {
    protected WordSplitter decoratedWordSplitter;
 
    abstract public List<String> getWords(String wordString);
}
 
/**
Декоратор, який видаляє слова з не більше ніж двома буквами
*/
class ShortWordsFilteringSplitter extends FilteringSplitter {
 
    public ShortWordsFilteringSplitter(WordSplitter wordSplitter) {
        decoratedWordSplitter = wordSplitter;
    }
 
    public List<String> getWords(String wordString) {
        List<String> wordList = decoratedWordSplitter.getWords(wordString);
        for (int i = 0; i < wordList.size();) {
            if (wordList.get(i).length() <= 2) {
                wordList.remove(i);
            } else {
	    	++i;
	    }
        }
        return wordList;
    }
}
 
/**
Декоратор, який видаляє зі списку слова, що починаються з заглавної букви
*/
class PropperNamesFilteringSplitter extends FilteringSplitter {
 
    public PropperNamesFilteringSplitter(WordSplitter wordSplitter) {
        decoratedWordSplitter = wordSplitter;
    }
 
    public List<String> getWords(String wordString) {
        List<String> wordList = decoratedWordSplitter.getWords(wordString);
        for (int i = 0; i < wordList.size();) {
	    String word = wordList.get(i);
            if (word.isEmpty() || Character.isUpperCase(word.charAt(0))) {
                wordList.remove(i);
            } else {
	    	++i;
	    }
        }
        return wordList;
    }
}
 
class Main {   
    public static void main(String[] args) {
        WordSplitter wordSplitter = new PropperNamesFilteringSplitter(new ShortWordsFilteringSplitter(new PureWordSplitter()));
        List<String> result = wordSplitter.getWords("no hi Afrika yes ambitious come Ukraine Ua");
        for (String word : result) {
            System.out.print(word + " ");
        } 
    }
}

Зауваження і коментарі[ред.ред. код]

  • Хоча об'єкт-декоратор може додавати свою функціональність до або після функціональності основного об'єкта, ланцюжок створюваних об'єктів завжди повинен закінчуватися об'єктом класу ConcreteComponent.
  • Базові класи мови Java широко використовують шаблон Декоратор для організації обробки операцій введення-виведення.

Посилання[ред.ред. код]

Література[ред.ред. код]

Алан Шаллоуей, Джеймс Р. Тротт Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М.: «Вильямс», 2002. — 288 с. — ISBN 0-201-71594-5