mboost-dp1
Java Command Design Pattern
- Forside
- ⟨
- Forum
- ⟨
- Programmering
Nogen der er hajer til design patterns, specielt Command?
Et eksempel...
For at kunne bruge Undo/Redo funktionalitet i et program jeg er ved at lave, er jeg faldet over Command.
Jeg er dog lidt forvirret. Jeg forstår at hver eneste klasse som implementerer Command, har mulighed for at fx gemme den action og 'state' som skal til for at gengive den på et andet tidspunkt (fx i forbindelse med undo), MEN... Command kalder kun en metode, Execute() der ikke returnerer noget.
Mit spørgsmål er, hvad er den bedste måde at få et resultat tilbage på ved at kalde en void Execute() metode på et Command object?
Indtil videre har jeg brugt callback (ligesom i eksemplet øverst), dvs. inkluderet det object hvis states skal opdateres i forbindelse med et kald til Execute().
Jeg er synes dog det er lidt overkill, at man først skulle kalde Execute() ... og dernæst 'staten' på det object som Execute() skulle ændre... og noget andet er, hvad med Exceptions?
Mit problem er, at jeg har Actions, der implementerer Command, men som skal returnere et object.
Et eksempel...
/* The Invoker class */
public class Switch {
private Command flipUpCommand;
private Command flipDownCommand;
public Switch(Command flipUpCmd, Command flipDownCmd) {
this.flipUpCommand = flipUpCmd;
this.flipDownCommand = flipDownCmd;
}
public void flipUp() {
flipUpCommand.execute();
}
public void flipDown() {
flipDownCommand.execute();
}
}
/* The Receiver class */
public class Light {
public Light() { }
public void turnOn() {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
/* The Command interface */
public interface Command {
void execute();
}
/* The Command for turning on the light */
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight=light;
}
public void execute(){
theLight.turnOn();
}
}
/* The Command for turning off the light */
public class FlipDownCommand implements Command {
private Light theLight;
public FlipDownCommand(Light light) {
this.theLight=light;
}
public void execute() {
theLight.turnOff();
}
}
/* The test class or client */
public class PressSwitch {
public static void main(String[] args) {
Light lamp = new Light();
Command switchUp = new FlipUpCommand(lamp);
Command switchDown = new FlipDownCommand(lamp);
// See criticism of this model above:
// The switch itself should not be aware of lamp details (switchUp, switchDown)
// either directly or indirectly
Switch s = new Switch(switchUp,switchDown);
try {
if (args[0].equalsIgnoreCase("ON")) {
s.flipUp();
} else if (args[0].equalsIgnoreCase("OFF")) {
s.flipDown();
} else {
System.out.println("Argument \"ON\" or \"OFF\" is required.");
}
} catch (Exception e){
System.out.println("Arguments required.");
}
}
}
For at kunne bruge Undo/Redo funktionalitet i et program jeg er ved at lave, er jeg faldet over Command.
Jeg er dog lidt forvirret. Jeg forstår at hver eneste klasse som implementerer Command, har mulighed for at fx gemme den action og 'state' som skal til for at gengive den på et andet tidspunkt (fx i forbindelse med undo), MEN... Command kalder kun en metode, Execute() der ikke returnerer noget.
Mit spørgsmål er, hvad er den bedste måde at få et resultat tilbage på ved at kalde en void Execute() metode på et Command object?
Indtil videre har jeg brugt callback (ligesom i eksemplet øverst), dvs. inkluderet det object hvis states skal opdateres i forbindelse med et kald til Execute().
Jeg er synes dog det er lidt overkill, at man først skulle kalde Execute() ... og dernæst 'staten' på det object som Execute() skulle ændre... og noget andet er, hvad med Exceptions?
Mit problem er, at jeg har Actions, der implementerer Command, men som skal returnere et object.
#1
For mere info end Wikipedia se f.eks.:
http://www.javaworld.com/javaworld/javatips/jw-jav...
http://geekswithblogs.net/davenet/articles/101320....
Det sidste viser noget UnDo og ReDo.
For mere info end Wikipedia se f.eks.:
http://www.javaworld.com/javaworld/javatips/jw-jav...
http://geekswithblogs.net/davenet/articles/101320....
Det sidste viser noget UnDo og ReDo.
arne_v (3) skrev:#1
Det korte svar er vel at den state gemmes i instansen af den konkrete command klasse.
Det ville jeg også mene ville være en lige til måde at implementere det på.
squad2nd (1) skrev:Mit problem er, at jeg har Actions, der implementerer Command, men som skal returnere et object.
Umiddelbart ser jeg ingen grund til at Commands skal returnere noget objekt, da operationen (som Command'en udfører) er indeholdt i Command-objektet selv. Da du giver objektet med som Command-objektet opererer på, kan du blot efterfølgende kigge på dets tilstand.
For at få "Undo" og "Redo" implementeret, er det vel blot at udvide Command-objektet med tilsvarende metoder (hvor redo vil kalde execute-metoden, og undo fører objektet tilbage til dets oprindelige tilstand).
#5
Det var det jeg tænkte.
Teoretisk: Hvis jeg har et object som har en metode som returnerer en ArrayList fx fra en database af nogen personer, så kræver det vel at jeg er nødt til at gemme en reference af den ArrayList på selve objektet, istedet for bare at returnere den med det samme?
Dvs. sådan noget ala det nedenstående, er ikke muligt ved at bruge Command?
Som I nok kan høre, er jeg lidt forvirret.
Da du giver objektet med som Command-objektet opererer på, kan du blot efterfølgende kigge på dets tilstand.
Det var det jeg tænkte.
Teoretisk: Hvis jeg har et object som har en metode som returnerer en ArrayList fx fra en database af nogen personer, så kræver det vel at jeg er nødt til at gemme en reference af den ArrayList på selve objektet, istedet for bare at returnere den med det samme?
Dvs. sådan noget ala det nedenstående, er ikke muligt ved at bruge Command?
interface Command
{ void execute() }
public class GetDataFromDatabase implements Command
{
private DatabaseList dbList;
public GetDataFromDatabase(DatabaseList g)
{
dbList = g;
}
public void execute()
{
dbList.getSomeDataFromDatabase();
}
}
public class DatabaseList
{
public ArrayList getSomeDataFromDatabase()
{
ArrayList f = //connect to database, and get some database
return f;
}
// Eller...
private ArrayList dataFromDb;
public void getSomeDataFromDatabase()
{
this.dataFromDb = //connect to database, and get some database
}
public ArrayList getDbData()
{
return dataFromDb;
}
}
Som I nok kan høre, er jeg lidt forvirret.
#6
Jamen, hov hov....
Så vidt jeg forstår brugen af Command pattern er det til at enkapsulere en operation der foretager en ændring, derfor giver det også mening at lave en "undo" på denne operation.
F.eks, en Command der gemmer et tilføjer et objekt (eller rettere sagt, en objekt-til-relationel mapping af selv samme - hvis vi taler om databaser), når man så undo'er, "slettes" objektet.
Der er dog ingen måde til at undo operationen at "hente data", derfor vil jeg ikke mene at brugen af Command-pattern passer til det at populere en liste-ADT.
Men der er min generelle forståelse, samt (min pragmatiske) brug af Command-pattern.
Jamen, hov hov....
Så vidt jeg forstår brugen af Command pattern er det til at enkapsulere en operation der foretager en ændring, derfor giver det også mening at lave en "undo" på denne operation.
F.eks, en Command der gemmer et tilføjer et objekt (eller rettere sagt, en objekt-til-relationel mapping af selv samme - hvis vi taler om databaser), når man så undo'er, "slettes" objektet.
Der er dog ingen måde til at undo operationen at "hente data", derfor vil jeg ikke mene at brugen af Command-pattern passer til det at populere en liste-ADT.
Men der er min generelle forståelse, samt (min pragmatiske) brug af Command-pattern.
#7
Jeg tænkte nok at man kun kunne kalde en metode og ikke få noget returneret igen.
Grunden til at jeg er forvirret er fordi at jeg er ved at bruge det interface i forbindelse med Swing, og dér har jeg givet en klasse til hver ActionListener. Altså fx:
... men der er vel ingen grund til at bruge et Command interface når allerede "er" et ActionListener interface tilstede? Så kunne man vel oprette en UndoList med hver ActionListener der er blevet kaldt, eller hvad?
(jeg ved godt at Swing har sin egen UndoManager man kan bruge, men jeg tænkte jeg ville lære lidt low-level først)
Jeg tænkte nok at man kun kunne kalde en metode og ikke få noget returneret igen.
Grunden til at jeg er forvirret er fordi at jeg er ved at bruge det interface i forbindelse med Swing, og dér har jeg givet en klasse til hver ActionListener. Altså fx:
class OpenFileDialog implements ActionListener
... men der er vel ingen grund til at bruge et Command interface når allerede "er" et ActionListener interface tilstede? Så kunne man vel oprette en UndoList med hver ActionListener der er blevet kaldt, eller hvad?
(jeg ved godt at Swing har sin egen UndoManager man kan bruge, men jeg tænkte jeg ville lære lidt low-level først)
Jeg tror du forveksler interfaces med patterns.
Et command pattern kan ikke sammenlignes med en action listener. At signaturen for et command pattern kan minde om det fra en action listener, gør dem ikke til de samme.
Jeg vil umiddelbart fraråde dig at bruge Listeners som Command-objekter, så hellere lave en implementation af UndoableEdit (eller AbstractUndoableEdit), da disse er møntet på lige netop Command-pattern.
Hvis du vil have yderligere seperation, ville jeg dog lave mit eget Command interface (da det kun ville indeholde 1-3 metoder er det nok lige til at overkomme), og så bruge Adapter pattern til at få dette til at passe ind i Swing's arkitektur.
Dette vil yderligere give dig muligheden for at skifte valg af UI framework, hvis du senere ville kigge på SWT eller webbaserede teknologier (GWT heriblandt)
Et command pattern kan ikke sammenlignes med en action listener. At signaturen for et command pattern kan minde om det fra en action listener, gør dem ikke til de samme.
Jeg vil umiddelbart fraråde dig at bruge Listeners som Command-objekter, så hellere lave en implementation af UndoableEdit (eller AbstractUndoableEdit), da disse er møntet på lige netop Command-pattern.
Hvis du vil have yderligere seperation, ville jeg dog lave mit eget Command interface (da det kun ville indeholde 1-3 metoder er det nok lige til at overkomme), og så bruge Adapter pattern til at få dette til at passe ind i Swing's arkitektur.
Dette vil yderligere give dig muligheden for at skifte valg af UI framework, hvis du senere ville kigge på SWT eller webbaserede teknologier (GWT heriblandt)
#10
Kan være du har ret, og forfatteren ikke er klog nok, men
ifølge dette her dokument om Command pattern:
Mit problem er egenligt Swing. Hvis du gider, og har lyst, vil jeg være meget taknemmelig hvis du kunne skrive et lille eksempel til mig i Java... bare et simpelt program hvor man trykker på en jbutton og den så kalder et Command object.
Et command pattern kan ikke sammenlignes med en action listener.
Kan være du har ret, og forfatteren ikke er klog nok, men
ifølge dette her dokument om Command pattern:
But there are still a couple of more ways to approach this. If you give every control its own actionListener class, you are in effect creating individual command objects for each of them. And, in fact, this is really what the designers of the Java 1.1 event model had in mind.
Mit problem er egenligt Swing. Hvis du gider, og har lyst, vil jeg være meget taknemmelig hvis du kunne skrive et lille eksempel til mig i Java... bare et simpelt program hvor man trykker på en jbutton og den så kalder et Command object.
squad2nd (11) skrev:#10
Kan være du har ret, og forfatteren ikke er klog nok, men
ifølge dette her dokument om Command pattern:But there are still a couple of more ways to approach this. If you give every control its own actionListener class, you are in effect creating individual command objects for each of them. And, in fact, this is really what the designers of the Java 1.1 event model had in mind.
Jeg synes ikke de 2 udtalelser modsiger hinanden.
Min pointe er at en listener reagerer på events (og er UI og API specifik - oftest), en Command er pattern der eksekveres på baggrund af en event.
squad2nd (11) skrev:
Mit problem er egenligt Swing. Hvis du gider, og har lyst, vil jeg være meget taknemmelig hvis du kunne skrive et lille eksempel til mig i Java... bare et simpelt program hvor man trykker på en jbutton og den så kalder et Command object.
Jeg prøver lige at hacke noget sammen, men hvis det ikke virker, vil jeg undskylde det med det faktum at jeg har befundet mig i SWT-verdenen de sidste 5 år, sorry:
// Listener-registration etc.
JTextArea jTextArea1 = ….
UndoManager undoMgr = ...
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
UndoableEdit adapter = new CommandAdapter(new CutCommand(jTextArea1));
undoMgr.undoableEditHappened(new UndoableEditEvent(e.getSource(), adapter);
}
});
// Interfaces and Classes, for Command(s) and "Swing"-API-wrapper
interface Command {
void execute();
void undo();
}
class CutCommand implements Command {
… field members…
public CutCommand(JTextArea area) {
this.area = area;
this.selection = area.getSelection(); // whatever the method is named
this.contents = area.getText();
}
void execute() {
// put selection on Clipboard and remove from area
}
void undo() {
// restore contents of area, and remove selection from Clipboard
}
}
class CommandAdapter extends AbstractUndoableEdit {
… field members…
public CommandAdapter(Command command) {
this.command = command;
}
public void undo() throws CannotUndoException() {
command.undo();
}
public void redo() throws CannotRedoException() {
command.redo();
}
… canUndo, and canRedo-methods goes here…
}
Jeg har primært udviklet professionelt i UI / Application layer af Java applikationer på Desktop området. Heriblandt alt fra simple UI layouts, til mere komplekse grafiske vektor-baserede editorer.
På fritidsbasis er jeg mere interesseret i multitier applikationer, og roder med GWT, Web (HTML, CSS), PHP, Grails, diverse Java web frameworks (Struts...yuk, og Spring...knap så yuk) og andet i den retning.
På fritidsbasis er jeg mere interesseret i multitier applikationer, og roder med GWT, Web (HTML, CSS), PHP, Grails, diverse Java web frameworks (Struts...yuk, og Spring...knap så yuk) og andet i den retning.
Gå til top
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.