+ All Categories
Home > Documents > Vzor P říkaz - Command Vzor Návšt ěvník -...

Vzor P říkaz - Command Vzor Návšt ěvník -...

Date post: 24-Jan-2020
Category:
Upload: others
View: 12 times
Download: 0 times
Share this document with a friend
59
SW_12 1 Vzor Příkaz - Command Vzor Návštěvník - Visitor
Transcript

SW_12

1

Vzor Příkaz - CommandVzor Návštěvník - Visitor

Vzor Příkaz - Command

• Problém:• Standardní cesta pro vykonání metody je její

vyvolání. • V některých situacích nejsme schopni řídit

načasování (timing) kontextu, ve kterém by

2

načasování (timing) kontextu, ve kterém by se měly metody volat.

• Dalším problémem je flexibilní zpracování návratové hodnoty metody.

Vzor Příkaz - Command

• Kontext:• Jak ovládat řadu zařízení přes dálkový

ovladač. • Požadujeme, aby ovladač měl jednoduché

funkce a abychom byli schopni modifikovat

3

funkce a abychom byli schopni modifikovat jím ovládaná zařízení (přidat nové, odebrat původní).

Vzor Příkaz

• Řešení:• Zapouzdření operace do formy objektu typu

command.• Oddělení požadavku na danou akci od

objektu, který skutečně akci provede.

4

objektu, který skutečně akci provede. • Návrhový vzor Command právě oddělí

uvedené části od sebe.

Vzor Příkaz

• Vzor si vysvětleme na příkladu dálkového ovladače (remote controller), který bude skutečným žadatelem (requester) provedení konkrétních akcí, které zvolíme stiskem daných tlačítek ovladače.

5

• Požadavek pak provede konkrétní třída daného zařízení.

Vzor Příkaz

• Jednoduchými požadovanými operacemi mohou být požadavky na rozsvícení, zhasnutísvětla, zapnutí, vypnutí televizoru.

• Objekt command pak bude provádět tuto konkrétní operaci.

6

konkrétní operaci. • Bude třeba tedy vytvořit řadu objektů

command pro každé tlačítko vzdáleného ovladače, které pak zabezpečí vykonání konkrétní operace.

Postup

1. Klient vytvoří objekt command.2. Klient vykoná metodu setCommand()

k uložení objektu command do invokátoru(vyvolávače).

3. Později klient požádá invokátor o provedení

7

3. Později klient požádá invokátor o provedení objektu command.

• Projevuje se snaha ukládat tyto objekty command do nějaké kolekce a pak je vyvolat.

• Využití při událostmi řízeném programování.

Postup

• Za zmínku stojí, že poté, co je objekt command nahrán do invokátoru (metodou setCommand()), může být objekt commandvyužit jednou nebo vícekrát, nebo také zrušen či nahrazen jiným objektem command.

8

command.

Poznámkypublic interface Command {

public void execute();

}

Vytvoření prvního objektu command

Předtím, než vytvoříme první objekt command, který bude rozsvěcet světlo, deklarujeme nejdříve rozhraní, které bude využívat vzdálený ovladač.

Poznámkypublic class LightOnCommand implements Command {

private Light light;

public LightOnCommand(Light light) { // konstruktor

this.light = light;

}

public void execute() {

light.on();

}

}

Jediná metoda rozhraní se jmenuje execute().

Následuje třída „konkrétní“ Command(LightOnCommand), (LightOnCommand), která implementuje rozhraní Command.

Poznámkypublic class Light {

// konstruktor

public Light() { }

public void on() {

System.out.println("Light is on");

}

public void off() {

System.out.println("Light is off");

}

}

Vidíme, že třída Lightdeklaruje datový atribut light (světlo), který je nastaven v konstruktoru. Implementace metody exekute() pak vyvolá metodu on() třídy Light, metodu on() třídy Light, čímž se rozsvítí světlo.

Třída Light (světlo) má jistě i metodu off(), kterou se světlo zhasne.

Poznámkypublic class SimpleRemoteControl {

Command slot; // místo pro zařízení

public SimpleRemoteControl() {} // konstruktor

public void setCommand(Command command) {

slot = command;

}

public void buttonWasPressed() {

slot.execute();

}

}

Použití objektu command

Předpokládejme, že máme dálkový ovladač s jedním tlačítkem a odpovídajícím místem (pozicí, slotem) pro zařízení, které budeme dálkovým ovladačem řídít.

Metoda setCommand()Metoda setCommand()nastavuje konkrétné objekt command do proměnné slot. Při změně objektu command, musíme tuto metodu vyvolat znova. Metoda buttonWasPressed() je vyvolána vždy při stisku tlačítka.

Poznámkypublic class RemoteControlTest {

public static void main(String[] args) {

SimpleRemoteControl remote = new

SimpleRemoteControl();

// objekt light je příjemcem požadavku

Light light = new Light();

LightOnCommand lightOn = new LightOnCommand(light);

remote.setCommand(lightOn);

remote.buttonWasPressed();

}

}

Jednoduchý test funkčnosti je pak následující:

Třída RemoteControlTestpředstavuje klienta ve představuje klienta ve vzoru Command. Objekt remote je náš invoker(ten, kdo se něčeho dovolává) a je mu předán konkrétní objekt commanderu v metodě setCommand().

Vzor Příkaz - definování

• Vzor Command zapouzdřuje pořadavek(request) jako objekt a tím nám dovoluje parametrizovat další objekty s odlišnými požadavky, frontovat nebo zaznamenávat požadavky a podporovat operaci undo(zrušení provedené operace).

14

(zrušení provedené operace).

Vzor Příkaz - definování

• Víme, že objekt command svazuje dohromady množinu akcí na konkrétním příjemci.

• Příjemcem bylo světlo, ale mohou to být např. garážová vrata, u kterých můžeme požadovat

15

garážová vrata, u kterých můžeme požadovat akce: zavření, otevření, zastavení, zhasnutísvětla v garáži, rozsvícení světla v garáži.

• Abychom toho dosáhli, vzor pakuje akce a příjemce do jednoho objektu, který vystavuje jednu metodu execute().

Vzor Příkaz - definování

• Když je objekt vyvolán, metoda execute()způsobí vyvolání akcí příjemce.

• Z vnějšího pohledu žádné jiné objekty skutečně neví, jaké akce jsou na příjemci vykonány; tyto objekty pouze ví, že když

16

vykonány; tyto objekty pouze ví, že když vyvolají metodu execute(), jejich požadavek bude obsloužen.

Vzor Příkaz - definování

• Podíváme se blíže na garáž. Vidíme, že se jedná celkem o pět akcí.

• Musíme proto doplnit odpovídající objekty command pro každou akci.

17

Poznámkypublic class GarageDoor {

public GarageDoor() { }

public void up() {

System.out.println("Garage Door is Open");

}

public void down() {

System.out.println("Garage Door is Closed");

}

public void stop() {

System.out.println("Garage Door is Stopped");

}}

public void lightOn() {

System.out.println("Garage light is on");

}

public void lightOff() {

System.out.println("Garage light is off");

}

}

Poznámkypublic class GarageDoorOpenCommand implements Command {

GarageDoor garageDoor;

public GarageDoorOpenCommand(GarageDoor garageDoor) {

this.garageDoor = garageDoor;

}

public void execute() {

garageDoor.up();

}

}

Poznámkypublic class RemoteControlTest {

public static void main(String[] args) {

SimpleRemoteControl remote = new

SimpleRemoteControl();

GarageDoor garageDoor = new GarageDoor();

GarageDoorOpenCommand garageOpen =

new GarageDoorOpenCommand(garageDoor);

remote.setCommand(garageOpen);

remote.buttonWasPressed();

}

}

Diagram t říd

21

Aplikace

• Rozhraní Command je rozhraní v našem případě zatím pouze s metodou execute().

• Třída ConcreteCommand je v našich příkladech reprezentovaná třídami LightOnCommand a

22

LightOnCommand a GarageDoorOpenCommand.

• Třídu Receiver (příjemce) reprezentují konkrétní třídy Light (světlo) a GarageDoor. Třída Invoker s metodou setCommand() je reprezentovaná třídou SimpleRemoteControl.

Aplikace

• Třída Client je reprezentovaná třídou s hlavní metodou, tedy třídou RemoteControlTest.

• Třída Client je zodpovědná za vytváření objektů tříd ConcreteCommand a nastavení jejich příjemce (receiver).

23

jejich příjemce (receiver). • Třída Invoker uchovává objekt command a

v daném místě žádá objekt command o provedení požadavku, vyvoláním jeho metody execute().

Aplikace

• Třída ConcreteCommand definuje vazbu mezi akcí a příjemcem.

• Invoker vyvolá požadavek vyvoláním metody execute() a objekt concreteCommand to vykoná vyvoláním jedné nebo více akcí na

24

vykoná vyvoláním jedné nebo více akcí na příjemci.

• Příjemce (receiver) zná, jak provést konkrétní požadavek.

• Jako příjemce může sloužit libovolná třída.

Aplikace

• Nyní se podíváme, jak bychom řešili vzdálený ovladač pro sedm zařízení.

• Pokud budeme ovládat např. světlo v kuchyni a světlo v obývacím pokoji, nutně potřebujeme dva konkrétní objekty command,

25

potřebujeme dva konkrétní objekty command, jeden pro světlo v kuchyni a druhý pro světlo v obývacím pokoji.

• Vzor Command to neumí rozlišit.

Aplikace

• Další věc, kterou musíme zavést, jsou polepro nastavení jednotlivých zařízení.

• Tato pole povedeme dvoje a to pro zapnutí a vypnutí, což jsou nejzákladnější operace.

26

Poznámkypublic class RemoteControl {

Command[] onCommands; // pole pro zapnutí

Command[] offCommands; // pole pro vypnutí

public RemoteControl() {

onCommands = new Command[7];

offCommands = new Command[7];

Command noCommand = new NoCommand();

for (int i = 0; i < 7; i++) {

onCommands[i] = noCommand;

offCommands[i] = noCommand;

}

}

public void setCommand(int slot, Command onCommand,

Command offCommand) {

onCommands[slot] = onCommand;

offCommands[slot] = offCommand;

}

public void onButtonWasPushed(int slot) {

onCommands[slot].execute();

}

Poznámkypublic void offButtonWasPushed(int slot) {

offCommands[slot].execute();

}

public String toString() {

StringBuffer stringBuff = new StringBuffer();

stringBuff.append("\n---- Remote Control -----\n");

for (int i = 0; i < onCommands.length; i++) {

stringBuff.append("[slot " + i + "] " +

onCommands[i].getClass().getName()

+ " " + offCommands[i].getClass().getName()

+ "\n");

}

return stringBuff.toString();

}}

}

Poznámkypublic class NoCommand implements Command {

public void execute() { }

}

Vzdálený ovladač ovládá sedm jednoduchých zařízení (zapnutí / vypnutí). Na začátku třídy nastavíme všechny přepínače na objekt noCommand, jehož třídu uvádíme. uvádíme. To znamená, že pokud nějaký přepínač nebude definovaný, implicitně bude jako noCommand, tedy prázdná metoda execute().

Aplikace

• Metoda setCommand() má tři parametry pro uchování všech informací.

• Prvním parametrem je slot, který tvoří index pro uložení informací v polích.

• Další dva parametry jsou pro konkrétní

30

• Další dva parametry jsou pro konkrétní objekty command pro zapnutí a pro vypnutí.

• Metoda toString() vypisuje všechna nastavení této třídy.

Poznámkypublic class StereoOnWithCDCommand implements Command {

Stereo stereo;

public StereoOnWithCDCommand(Stereo stereo) {

this.stereo = stereo;

}

public void execute() {

stereo.on();

stereo.setCD();

stereo.setVolume(11);

}

}

Třída StereoOnWithCDCommandmůže mít pak následný kód:

Poznámkypublic class Stereo {

String location;

public Stereo(String location) {

this.location = location;

}

public void on() {

System.out.println(location + " stereo is on");

}

public void off() {

System.out.println(location + " stereo is off");

}

Tato třída konkrétního commandu spouští stereo, spouští CD přehravač s hlasitistí11. Třída příjemce (receiver) má následující kód.

public void setCD() {

System.out.println(location +

" stereo is set for CD input");

}

public void setDVD() {

System.out.println(location +

" stereo is set for DVD input");

}

Poznámkypublic void setRadio() {

System.out.println(location +

" stereo is set for Radio");

}

public void setVolume(int volume) {

// code to set the volume

// valid range: 1-11 (after all 11 is better than

// 10, right?)

System.out.println(location +

" Stereo volume set to " + volume);

}

}

Poznámkypublic class RemoteLoader {

public static void main(String[] args) {

RemoteControl remoteControl = new RemoteControl();

Light livingRoomLight = new Light("Living Room");

Light kitchenLight = new Light("Kitchen");

CeilingFan ceilingFan=

new CeilingFan("Living Room");

GarageDoor garageDoor = new GarageDoor("");

Stereo stereo = new Stereo("Living Room");

LightOnCommand livingRoomLightOn =

new LightOnCommand(livingRoomLight);

LightOffCommand livingRoomLightOff =

new LightOffCommand(livingRoomLight);

LightOnCommand kitchenLightOn =

K otestování našeho postupu pak bude sloužit třída RemoteLoader.

LightOnCommand kitchenLightOn =

new LightOnCommand(kitchenLight);

LightOffCommand kitchenLightOff =

new LightOffCommand(kitchenLight);

CeilingFanOnCommand ceilingFanOn =

new CeilingFanOnCommand(ceilingFan);

CeilingFanOffCommand ceilingFanOff =

new CeilingFanOffCommand(ceilingFan);

GarageDoorUpCommand garageDoorUp =

new GarageDoorUpCommand(garageDoor);

GarageDoorDownCommand garageDoorDown =

new GarageDoorDownCommand(garageDoor);

PoznámkyStereoOnWithCDCommand stereoOnWithCD =

new StereoOnWithCDCommand(stereo);

StereoOffCommand stereoOff =

new StereoOffCommand(stereo);

remoteControl.setCommand(0, livingRoomLightOn,

livingRoomLightOff);

remoteControl.setCommand(1, kitchenLightOn,

kitchenLightOff);

remoteControl.setCommand(2, ceilingFanOn,

ceilingFanOff);

remoteControl.setCommand(3, stereoOnWithCD,

stereoOff);

System.out.println(remoteControl);System.out.println(remoteControl);

remoteControl.onButtonWasPushed(0);

remoteControl.offButtonWasPushed(0);

remoteControl.onButtonWasPushed(1);

remoteControl.offButtonWasPushed(1);

remoteControl.onButtonWasPushed(2);

remoteControl.offButtonWasPushed(2);

remoteControl.onButtonWasPushed(3);

remoteControl.offButtonWasPushed(3);

}

}

Aplikace

• Jak jste si všimli, objekt třídy NoCommand je příkladem null objektu.

• Ten také slouží k návratu objektu z metody, když „nemáme“ co poslat zpět.

36

Poznámkypublic interface Command {

public void execute();

public void undo();

} Přidání metody undo do rozhraní Command

Když rozhraní Commandpodporuje metodu undo, musíme ji doplnit nejdříve do rozhraní.

Poznámkypublic class LightOnCommand implements Command {

Light light;

public LightOnCommand(Light light) {

this.light = light;

}

public void execute() {

light.on();

}

public void undo() {

light.off();

}

}

Teď se podíváme, jak budeme metodu undo()implementovat do tříd konkrétních commandů.

Ukážeme si to na příkladu rozsvícení a zhasnutí světla.

}

Poznámkypublic class LivingroomLightOffCommand implements Command {

Light light;

public LivingroomLightOffCommand(Light light) {

this.light = light;

}

public void execute() {

light.off();

}

public void undo() {

light.on();

}

}

Vidíme, že operace on() a off() jsou opačné. Ještě musíme opravit třídu RemoteControl.

Poznámkypublic class RemoteControl {

Command[] onCommands;

Command[] offCommands;

Command undoCommand;

public RemoteControl() {

onCommands = new Command[7];

offCommands = new Command[7];

Command noCommand = new NoCommand();

for(int i=0;i<7;i++) {

onCommands[i] = noCommand;

offCommands[i] = noCommand;

}

undoCommand = noCommand;undoCommand = noCommand;

}

public void setCommand(int slot, Command onCommand, Command offCommand) {

onCommands[slot] = onCommand;

offCommands[slot] = offCommand;

}

Poznámkypublic void onButtonWasPushed(int slot) {

onCommands[slot].execute();

undoCommand = onCommands[slot];

}

public void offButtonWasPushed(int slot) {

offCommands[slot].execute();

undoCommand = offCommands[slot];

}

public void undoButtonWasPushed() {

undoCommand.undo();

}

public String toString() {public String toString() {

StringBuffer stringBuff = new StringBuffer();

stringBuff.append("\n---- Remote Control -----\n");

for (int i = 0; i < onCommands.length; i++) {

stringBuff.append("[slot " + i + "] " +

onCommands[i].getClass().getName()

+ " " + offCommands[i].getClass().getName() + "\n");

}

stringBuff.append("[undo] " +

undoCommand.getClass().getName() + "\n");

return stringBuff.toString();

}

}

Poznámkypublic class RemoteLoaderTest {

public static void main(String[] args) {

RemoteControl remoteControl = new RemoteControl();

Light livingRoomLight = new Light("Living Room");

LightOnCommand livingRoomLightOn =

new LightOnCommand(livingRoomLight);

LightOffCommand livingRoomLightOff =

new LightOffCommand(livingRoomLight);

remoteControl.setCommand(0, livingRoomLightOn,

livingRoomLightOff);

Objekty commandpak ještě mohou být ukládány do kolekcí a pak spouštěny najednou.

livingRoomLightOff);

remoteControl.onButtonWasPushed(0);

remoteControl.offButtonWasPushed(0);

System.out.println(remoteControl);

remoteControl.undoButtonWasPushed();

remoteControl.offButtonWasPushed(0);

remoteControl.onButtonWasPushed(0);

System.out.println(remoteControl);

remoteControl.undoButtonWasPushed();

}

}

Shrnutí vzoru P říkaz

• Tento vzor má řadu uplatnění, např. ošetřování chybových stavů, práce s událostmi řízených programech.

• Operace, která se má provést je „zabalena do objektu“ a pak se s ní dá pružně manipulovat.

43

objektu“ a pak se s ní dá pružně manipulovat. Klient je odstíněn od konkrétní implementace metody execute().

• Konkrétní metoda je vybrána podle typu objektu, který metodu execute() aktuálně vyvolává.

Shrnutí vzoru P říkaz

• Navíc možnost připojení objektu třídy noCommand a metoda undo().

• Konkrétní metoda je vybrána podle typu objektu, který metodu execute() aktuálně vyvolává.

44

vyvolává. • Navíc jsme viděli, jak se dá připojit objekt

třídy noCommand a metoda undo().

Vzor Command - p říkaz

• Příkazy vzoru Command se dají uložit do objektu třídy kolekce (např. Register)kvalifikovaného na objekt rozhraní Command.

• To pak vede k tomu, že se dá vytvořit dynamický seznam požadavků, které se

45

dynamický seznam požadavků, které se postupně provádějí.

Návšt ěvník - Visitor

• Kontext:• Je daná základní hierarchie tříd daného

problému, do které není možné dělat změny. • Může to být hierarchie tříd dodaná jiným

dodavatelem.

46

dodavatelem. • Jako změny myslíme dodání dalších

polymorfických metod, které by rozšířily funkčnost stávající hierarchie tříd.

Návšt ěvník - Visitor

• Problém:• Je třeba dodat další metody do hierarchie tříd

bez fyzického přidání daných metod do každé třídy uvedené hierarchie.

• Řešení:

47

• Řešení:• Řešení přináší návrhový vzor Visitor

(návštěvník), který dovoluje vytvoření oddělené hierarchie tříd typu Visitork virtualizaci operací prováděných na původníhierarchii tříd.

Konkrétní p říklad - diagram t říd

48

Návšt ěvník - Visitor

• Neměnnou strukturu tříd představují třídy na levé straně obrázku, tedy třídy Tvar, Kruh a Ctverec.

• Na pravé straně obrázku je pak hierarchie tříd, které se využívají na rozšíření funkčnosti

49

tříd, které se využívají na rozšíření funkčnosti stávající hierarchie.

• Jedná se nám o to, že chceme doplnit metody pro výpočet obsahu a obvodu daných obrazců.

Návšt ěvník - Visitor

• Postup při použití vzoru je následující:• Ve stávající (neměnné) hierarchii tříd

doplníme metodu accept() s argumentem instancí rozhraní Visitor do každé třídy.

• Abstraktní třída Tvar deklaruje metodu

50

• Abstraktní třída Tvar deklaruje metodu accept() jako abstraktní a její podtřídy ji pak implementují podle svých skutečných potřeb.

• Formální tvar je stejný, jen pseudoproměnná this je různá.

Poznámkypublic double accept(Visitor v) {

return v.visit(this);

}

• Podle počtu rozšiřujících metod, o které chceme rozšířit stávající hierarchii tříd, doplníme třídy implementující rozhraní Visitor.

V našem případě se jedná o třídy VisitObsah a VisitObvod, protože VisitObsah a VisitObvod, protože chceme doplnit operace počítající obsah a obvod obrazců.

Poznámkypublic class VisitObvod implements Visitor{

public double visit(Kruh c) {

return 2 * Math.PI * c.getPolomer();

}

public double visit(Ctverec s){

return 4 * s.getStrana();

}

}

Dále musíme vytvořit ve třídách VisitObsah a VisitObvod tolik metod visit(), kolik máme různých obrazců.

Protože máme dva Protože máme dva obrazce (Square a Circle), stačí nám dvě metody visit().

Návšt ěvník - Visitor

• Jedna metoda visit() počítá obvod kruhu a druhá metoda visit počítá obsah kruhu.

• Pro větší názornost uvedeme celý kód jednoduchého příkladu:

53

Poznámkypublic abstract class Tvar {

public abstract void vykresli();

public abstract void smaz();

public abstract double accept(Visitor v);

}

public class Kruh extends Tvar{

private int polomer;

public Kruh() {

polomer = 16;

}

public double accept(Visitor v) {

return v.visit(this);

}

public int getPolomer() {public int getPolomer() {

return polomer;

}

public void vykresli() {

System.out.println("Kruh.vykresli");

}

public void smaz() {

System.out.println("Kruh.smaz");

}

}

Poznámkypublic class Ctverec extends Tvar{

private int strana;

public Ctverec() {

strana = 12;

}

public double accept(Visitor v) {

return v.visit(this);

}

public int getStrana() {

return strana;

}

public void vykresli() {

System.out.println("Ctverec.vykresli");

}

public void smaz() { public void smaz() {

System.out.println("Ctverec.smaz");

}

}

public interface Visitor {

public double visit(Kruh c);

public double visit(Ctverec s);

}

Poznámkypublic class VisitObsah implements Visitor{

public double visit(Kruh c){

return Math.PI * c.getPolomer() * c.getPolomer();

}

public double visit(Ctverec s){

return s.getStrana() * s.getStrana();

}

}

public class VisitObvod implements Visitor{

public double visit(Kruh c) {

return 2 * Math.PI * c.getPolomer();

}

public double visit(Ctverec s){

return 4 * s.getStrana();return 4 * s.getStrana();

}

}

Poznámkypublic class TvarTest {

public static void main(String args[]) {

VisitObsah visitObsah = new VisitObsah();

VisitObvod visitObvod = new VisitObvod();

List <Tvar>tvary = new ArrayList<Tvar>();

tvary.add(new Ctverec());

tvary.add(new Kruh());

tvary.add(new Kruh());

tvary.add(new Ctverec());

tvary.add(new Kruh());

Iterator<Tvar>itr = tvary.iterator();

while(itr.hasNext()) {

Tvar s = itr.next();

s.vykresli();

s.smaz();s.smaz();

System.out.printf("Obsah obrazce: %s je: %.2f\n",

s.getClass().getName(),

s.accept(visitObsah));

System.out.printf("Obvod obrazce: %s je: %.2f\n",

s.getClass().getName(),

s.accept(visitObvod));

}

}

}

PoznámkyCtverec.vykresli

Ctverec.smaz

Obsah obrazce: Ctverec je: 144,00

Obvod obrazce: Ctverec je: 48,00

Kruh.vykresli

Kruh.smaz

Obsah obrazce: Kruh je: 804,25

Obvod obrazce: Kruh je: 100,53

Kruh.vykresli

Kruh.smaz

Obsah obrazce: Kruh je: 804,25

Obvod obrazce: Kruh je: 100,53

Ctverec.vykresli

Ctverec.smaz

Obsah obrazce: Ctverec je: 144,00Obsah obrazce: Ctverec je: 144,00

Obvod obrazce: Ctverec je: 48,00

Kruh.vykresli

Kruh.smaz

Obsah obrazce: Kruh je: 804,25

Obvod obrazce: Kruh je: 100,53

Shrnutí vzoru Návšt ěvník

• Je zřejmé, že můžeme zavést novou operaci (metodu) nad libovolnou strukturou, a to pouze dodáním nové třídy implementující rozhraní Visitor.

• Problém ale nastane, pokud rozšíříme

59

• Problém ale nastane, pokud rozšíříme stávající neměnnou strukturu tříd o další třídu.

• To však odporuje úvodnímu předpokladu, že struktura tříd je neměnná.


Recommended