Kiedy stosować wzór dekoratora?
Przeglądam moje wzorce projektowe, a jeden wzór, który muszę jeszcze poważnie wykorzystać w moim kodowaniu, to wzór dekoratora.
Rozumiem wzór, ale to, co chciałbym wiedzieć, to kilka dobrych konkretnych przykładów czasów w prawdziwym świecie, że wzór dekoratora jest najlepszym / optymalnym / eleganckim rozwiązaniem. Konkretne sytuacje, w których potrzeba wzoru dekoratora jest naprawdę przydatna.
Dzięki.7 answers
Wzór dekoratora jest często używany ze strumieniami: możesz owinąć strumień strumieniem, aby uzyskać dodatkową funkcjonalność. Widziałem to z. Net framework - z tego co wiem to występuje gdzie indziej. Moim ulubionym jest używanie GZipStream wokół strumienia plików, dla dodatkowej kompresji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 03:14:18
Wzór dekoratora służy do dodawania dodatkowych funkcji do określonego obiektu w przeciwieństwie do klasy obiektów. Łatwo jest dodać funkcjonalność do całej klasy obiektów poprzez podklasowanie obiektu, ale nie jest możliwe rozszerzenie pojedynczego obiektu w ten sposób. Za pomocą wzoru dekoratora można dodać funkcjonalność do pojedynczego obiektu i pozostawić inne podobne do niego niezmodyfikowane.
W Javie klasycznym przykładem wzorca dekoratora jest Java i / o Streams wdrożenie.
FileReader frdr = new FileReader(filename);
LineNumberReader lrdr = new LineNumberReader(frdr);
Poprzedni kod tworzy czytnik -- lrdr
-- który odczytuje z pliku i śledzi numery linii. Linia 1 tworzy czytnik plików (frdr
), a linia 2 dodaje śledzenie numeru linii.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 03:32:22
Ostatnio użyłem wzorca dekoratora w usłudze internetowej, która używa następującego interfejsu CommandProcessor:
public Command receive(Request request);
public Response execute(Command command);
public void respond(Response response);
Zasadniczo, Commandprocesor otrzymuje żądanie i tworzy odpowiednie polecenie, wykonuje polecenie i tworzy odpowiednią odpowiedź i wysyła odpowiedź. Kiedy chciałem dodać timing i zalogować go, stworzyłem TimerDecorator, który używał istniejącego Commandprocessora jako komponentu. TimerDecorator implementuje interfejs CommandProcessor, ale tylko dodaje timing, a następnie wywołuje swój cel, który jest prawdziwym Commandprocessorem. Coś takiego:
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
}
}
Więc prawdziwy procesor komend jest zawinięty wewnątrz Timerdecoratora i mogę traktować TimerDecorator tak jak docelowy procesor komend, ale teraz została dodana logika czasowa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 03:28:56
Dekorator jest prosty, ale niezwykle potężny. Ma kluczowe znaczenie dla osiągnięcia rozdzielenia obaw i jest niezbędnym narzędziem dla zasady otwartej zamkniętej. Weźmy przykład składania zamówienia na produkt:
IOrderGateway
{
void PlaceOrder(Order order);
{
Główna realizacja: AmazonAffiliateOrderGateway
Możliwymi dekoratorami mogą być:
IncrementPerformanceCounterOrderGateway
QueueOrderForLaterOnTimeoutOrderGateway
EmailOnExceptionOrderGateway
InterceptTestOrderAndLogOrderGateway
Spójrz tutaj dla bardziej szczegółowego przykładu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-23 09:28:20
Dekorator wzorzec dynamicznie zmienia funkcjonalność obiektu w czasie działania bez wpływu na istniejącą funkcjonalność obiektów.
Kluczowe przypadki użycia:
- dodawanie dodatkowych funkcjonalności/obowiązków dynamicznie
- Usuń funkcjonalności / obowiązki dynamicznie
- unikaj zbyt dużego podklasowania , aby dodać dodatkowe obowiązki.
Wady:
- nadużywanie Zasady Open Closed (otwarte dla rozszerzenia i zamknięte dla modyfikacji). Używaj tej funkcji oszczędnie tam, gdzie kod jest najmniej prawdopodobny.
- zbyt wiele małych klas i doda koszty utrzymania .
Przykład z prawdziwego świata: Oblicz cenę napoju, który może zawierać wiele smaków.
abstract class Beverage {
protected String name;
protected int price;
public Beverage(){
}
public Beverage(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
protected void setPrice(int price){
this.price = price;
}
protected int getPrice(){
return price;
}
protected abstract void decorateBeverage();
}
class Tea extends Beverage{
public Tea(String name){
super(name);
setPrice(10);
}
public void decorateBeverage(){
System.out.println("Cost of:"+ name +":"+ price);
// You can add some more functionality
}
}
class Coffee extends Beverage{
public Coffee(String name){
super(name);
setPrice(15);
}
public void decorateBeverage(){
System.out.println("Cost of:"+ name +":"+ price);
// You can add some more functionality
}
}
abstract class BeverageDecorator extends Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage){
this.beverage = beverage;
setName(beverage.getName()+"+"+getDecoratedName());
setPrice(beverage.getPrice()+getIncrementPrice());
}
public void decorateBeverage(){
beverage.decorateBeverage();
System.out.println("Cost of:"+getName()+":"+getPrice());
}
public abstract int getIncrementPrice();
public abstract String getDecoratedName();
}
class SugarDecorator extends BeverageDecorator{
public SugarDecorator(Beverage beverage){
super(beverage);
}
public void decorateBeverage(){
super.decorateBeverage();
decorateSugar();
}
public void decorateSugar(){
System.out.println("Added Sugar to:"+beverage.getName());
}
public int getIncrementPrice(){
return 5;
}
public String getDecoratedName(){
return "Sugar";
}
}
class LemonDecorator extends BeverageDecorator{
public LemonDecorator(Beverage beverage){
super(beverage);
}
public void decorateBeverage(){
super.decorateBeverage();
decorateLemon();
}
public void decorateLemon(){
System.out.println("Added Lemon to:"+beverage.getName());
}
public int getIncrementPrice(){
return 3;
}
public String getDecoratedName(){
return "Lemon";
}
}
public class VendingMachineDecorator {
public static void main(String args[]){
Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
beverage.decorateBeverage();
beverage = new SugarDecorator(new LemonDecorator(new Coffee("Cappuccino")));
beverage.decorateBeverage();
}
}
Wyjście:
Cost of:Assam Tea:10
Cost of:Assam Tea+Lemon:13
Added Lemon to:Assam Tea
Cost of:Assam Tea+Lemon+Sugar:18
Added Sugar to:Assam Tea+Lemon
Cost of:Cappuccino:15
Cost of:Cappuccino+Lemon:18
Added Lemon to:Cappuccino
Cost of:Cappuccino+Lemon+Sugar:23
Added Sugar to:Cappuccino+Lemon
Ten przykład oblicza koszt napoju w automacie po dodaniu wielu smaków do napoju.
W powyższym przykładzie:
Koszt herbaty = 10, cytryny = 3 i cukru = 5. Jeśli zrobisz cukier + cytryna + herbata, kosztuje 18. Koszt kawy =15, cytryny = 3, cukru = 5. Jeśli robisz cukier + cytryna + Kawa, kosztuje 23Dzięki zastosowaniu tego samego dekoratora dla obu napojów (herbaty i kawy) zmniejszono liczbę podklas. W przypadku braku wzoru dekoratora należy różne podklasy dla różnych kombinacji.
Kombinacje będą takie:
SugarLemonTea
SugarTea
LemonTea
SugarLemonCapaccuino
SugarCapaccuino
LemonCapaccuino
Itd.
Stosując ten sam dekorator dla obu napojów, zmniejszono liczbę podklas. Jest to możliwe ze względu na skład, a niedziedziczenie koncepcja użyta w tym wzorze.
Powiązane pytanie:
przydatne linki:
Design-wzory-dekorator by dzone
Dekorator by sourcemaking
Oodesign Artykuł
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-20 10:18:18
Zend Framework używa dekoratora dla elementów formularzy
Trochę więcej informacji: http://framework.zend.com/manual/en/zend.form.decorators.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-11 03:13:43
- aby dodawać zadania do poszczególnych obiektów dynamicznie i przejrzyście.
- za obowiązki, które można wycofać.
- gdy rozszerzenie przez podklasowanie jest niepraktyczne. Czasami możliwa jest duża liczba niezależnych rozszerzeń i spowodowałaby eksplozję podklas obsługujących każdą kombinację.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-29 00:30:52