今回は Command パターン(一覧)。
Command パターンの登場人物
- @Command → 型
- @Execute → メソッド
- @ConcreteCommand → 具象クラス
- commandType : Class<?>
- @ReceiverInstance → フィールド
- @Receiver → 型
- concreteCommandType : Class<?>
- @Invoker → 型
- commandType : Class<?>
- @Client → 具象クラス
- commandType : Class<?>
アノテーション定義
上記の定義の具体的な Java コード。
package org.waman.tools.design.gof.behavioral; import java.lang.annotation.*; public final class CommandPattern { private CommandPattern(){} @Target(ElementType.TYPE) public static @interface Command{ @Inherited @Target(ElementType.METHOD) public static @interface Execute{} } @Target(ElementType.TYPE) public static @interface ConcreteCommand{ Class<?> commandType() default Void.class; @Inherited @Target(ElementType.FIELD) public static @interface ReceiverInstance{} } @Target(ElementType.TYPE) public static @interface Receiver{ Class<?> concreteCommandType() default Void.class; } @Target(ElementType.TYPE) public static @interface Invoker{ Class<?> commandType() default Void.class; } @Target(ElementType.TYPE) public static @interface Client{ Class<?> commandType() default Void.class; } }
サンプルコード in 『Java 言語で学ぶデザインパターン入門』
Command.java
@Command 役のインターフェース。
import org.waman.tools.design.gof.behavioral.CommandPattern; import org.waman.tools.design.gof.behavioral.CommandPattern.Command.Execute; @CommandPattern.Command public interface Command { @Execute public abstract void execute(); }
MacroCommand.java
@ConcreteCommand 役のクラス、その1。
import org.waman.tools.design.gof.behavioral.CommandPattern; @CommandPattern.ConcreteCommand(commandType = Command.class) public class MacroCommand implements Command { ... @Override public void execute() {...} }
DrawCommand.java
import java.awt.Point; import org.waman.tools.design.gof.behavioral.CommandPattern; import org.waman.tools.design.gof.behavioral.CommandPattern.ConcreteCommand.ReceiverInstance; @CommandPattern.ConcreteCommand(commandType = Command.class) public class DrawCommand implements Command { @ReceiverInstance protected Drawable drawable; private Point position; ... @Override public void execute() { drawable.draw(position.x, position.y); } }
Drawable.java
@Receiver 役のクラス。 DrawCommand クラスにインスタンスを保持され、そこから処理を受け取ります。
import org.waman.tools.design.gof.behavioral.CommandPattern; @CommandPattern.Receiver(concreteCommandType = DrawCommand.class) public interface Drawable { public abstract void draw(int x, int y); }
DrawCanvas.java
Drawable インターフェースの実装クラス。 内部で Command#execute() を呼び出しているので、@Invoker 役となります。
import java.awt.*; import org.waman.tools.design.gof.behavioral.CommandPattern; @CommandPattern.Invoker(commandType = Command.class) public class DrawCanvas extends Canvas implements Drawable { private static final long serialVersionUID = -5768616080475206281L; ... public DrawCanvas(int width, int height, MacroCommand history) {...} @Override public void paint(Graphics g) { history.execute(); } @Override public void draw(int x, int y) {...} }
Main.java
@Invoker 役であり、@Client 役でもあるクラス。
@CommandPattern.Invoker(commandType = Command.class) @CommandPattern.Client(commandType = Command.class) public class Main extends JFrame implements ActionListener, MouseMotionListener, WindowListener { ... public Main(String title) {...} ... @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == clearButton) { history.clear(); canvas.repaint(); } } @Override public void mouseDragged(MouseEvent e) { Command cmd = new DrawCommand(canvas, e.getPoint()); history.append(cmd); cmd.execute(); } @Override public void windowClosing(WindowEvent e) { System.exit(0); } public static void main(String[] args) { new Main("Command Pattern Sample"); } }