11. デザインパターン(3/3)
当初予定: 構造に関するパターン Adapter, Composite, Decorator
補足:
GoF の古典的な23のデザインパターンに対して、 Java8 以降のコードで重要性が低くなるパターンについて考察されている。
※ interface のデフォルト実装と ラムダ(lambda)記法の導入が大きく影響している。
※※ Java 8 新機能つまみぐい Java8のラムダ記法についてはこちらの記事に簡潔な解説がある。
OOPのデザインパターンと関数型のデザインパターンを比較しながら、関数型プログラミング言語のコード作成について解説されている。JavaVMで動く関数型言語 Scala や同じくJVMで動くスクリプト言語Groovyを用い、解説している。
(先週の続き)
準備:
プロジェクトを作成する。
プロジェクト名 Project6
Project6の src フォルダに Project5 の src フォルダから L8_1.java や wav ファイルなど必要なものをコピーする。
src パッケージがない というエラーが出たら、 L8_1.java や関連ファイルを デフォルトパッケージに移動する。
class の整理:
L8_1 から不要なコードを削除する。 main メソッド や System.out.println()でのメッセージ出力など。
コマンドの実行タイミングの変更:
L8_1 の paintメソッドで history.execute() している部分を、マルチスレッドにより画面描画とは別のスレッドで実行されるように L8_1 を修正。
public class L8_1 extends Applet implements Runnable{
run メソッドを追加(コード修正機能)。ここでコマンドを実行するように、paintからコードを移動。
@Override
public void run() {
history.execute();
}
start メソッドを追加。(右クリック→ソース→メソッドのオーバーライド)
public void start() {
super.start();
(new Thread(this)).start();
}
Cat クラスを修正する:
class Cat extends Animal implements ItemOwner {
String item;
int x;
int y;
Image img;
Dir dir;
enum Dir {UP, DOWN, RIGHT, LEFT};
Cat のメソッド修正:
Cat(String name,Image img) {
super(name, Size.Small);
this.img = img;
dir = Dir.UP;
}
void walk(int step) {
// ねこが step 歩く
System.out.println(getName() + "が" + step + "歩移動" + dir.toString() + "方向に。");
switch(dir) {
case UP:
y -= step;
break;
case DOWN:
y += step;
break;
case RIGHT:
x += step;
break;
case LEFT:
x -= step;
}
}
コマンドのタイプを追加する:
class WalkCommand implements Command {
Cat cat;
public WalkCommand(Cat cat) {
this.cat = cat;
}
public void execute() {
cat.walk(10);
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class UpCommand implements Command {
Cat cat;
public UpCommand(Cat cat) {
this.cat = cat;
}
public void execute() {
cat.dir =Cat.Dir.UP;
}
}
その他のコマンドの作成は、受講生に任せる。
画面内に、キャラクターが描画されるようにする。
キャラクターの登録場所の準備:
private Stack<Cat> catstack = new Stack<Cat>();
キャラクターの登録例:
Cat mycat = new Cat("引っ越し",img);
catstack.push(mycat);
Cat mycat2 = new Cat("引っ越し2",img);
catstack.push(mycat2);
※ Catは catstack につまれている場合に画面に描画されるものとする。
キャラクター画像の読み込み例:
Image img;
img = getImage(getCodeBase(), "kohashi.jpg");
ペイントメソッドに、catstacckの猫を描画するコードを追加する。
public void paint(Graphics g) {
offg.setColor(Color.white);
offg.fillRect(0, 0, 600, 600); // 画面を消去する
for(Cat cat:catstack) {
offg.drawImage(cat.img, cat.x, cat.y, 50, 100, this);
}
g.drawImage(offimg, 0, 0, this); // オフスクリーンを描画
}
init メソッド内で新しく定義したコマンドを使用して、Cat に行動させる。
例)
右斜め下に、階段状に移動し、最後にアイテムを使用する。
Command cmd1 = new UseItemCommand(mycat);
Command cmdR = new RightCommand(mycat);
Command cmdW = new WalkCommand(mycat);
Command cmdU = new UpCommand(mycat);
Command cmdD = new DownCommand(mycat);
for(int i=0;i<10;i++) {
history.append(cmdR);
history.append(cmdW);
history.append(cmdD);
history.append(cmdW);
}
history.append(cmd1);
課題:
画面内に猫を複数登録し、それぞれ別々の行動を取らせる。
応用:
・Catが所持している Item も画面上に描画されるようにする。
Itemに Image のフィールドを作成する。
・Composite パターンを使用して、 Catに所属する Item として Cat 自身も所属できるようにする。
・Vistor パターンを使用して、画面に登録された全キャラクターを操作するコマンドを作成する。
指定した点に集合
キャラクターを指定して画面から削除
など。