【Android】【Applet】【Java】interface を使ってインスタンスを生成する 
2014/06/28 Sat [edit]
前回の続き。
実際にインスタンス生成のコードは少々やっかいである。new 演算子を使うには型(クラス名)が必要で、そのコードがメインコードに大量にあると、もはや使い回しなど出来なくなる。しかし、完全に無くすことはできなくても、interface を使って、そのコードを減らすことはできる。それはインスタンス生成用のインターフェイスを作ってしまう事である。その基本コードを書いてみよう。
●インスタンス生成用のインターフェイス(InstanceFactory)
public interface InstanceFactory<T> {
public T newInstance();
}
これはあくまでも簡単なものなので、必要に応じて色々作ってみると良いだろう。この手のインターフェイスは型を限定しないようにジェネリクス型を使う。とりあえず、ここでは実装には匿名クラスで定義してみよう。もちろん通常のクラスに implements して使っても構わない。
(参考)ジェネリクス型
(参考)総称型色々
●Android 版 インスタンス生成用のインターフェイス実装(匿名クラス)
InstanceFactory<XImage> factory = new InstanceFactory<XImage>() {
@Override
public XImage newInstance() {
return new AndroidImage();
}
};
●Applet 版 インスタンス生成用のインターフェイス実装(匿名クラス)
InstanceFactory<XImage> factory = new InstanceFactory<XImage>() {
@Override
public XImage newInstance() {
return new AppletImage();
}
};
どちらもインスタンスを生成して返してるだけである。
これが既にどこかに定義してあるとして、前回のメインコードを書き換えてみよう。
●インスタンス生成用のインターフェイス(InstanceFactory)がそれぞれ定義してあるとして、メインコードを書き換えてみる(共通)
//インスタンスを生成
XImage xImg = factory.newInstance();
//100 x 200 で画像を生成
xImg.createImage(100, 200);
dispSize(xImg);
これなら、どちらのプラットフォームでも使える事がわかるだろう。定義部分は簡易フレームワークで使った XActivity, XApplet のような抽象クラスに定義してしまうという手もある。頻繁に使うものなら、XFramework にメソッド追加しても良いだろう。
また、これを使えばメソッド内でインスタンス生成などもやり易くなる。簡単な例を挙げてみよう。
●インスタンス生成用のインターフェイスを引数にして画像を生成する(共通)
public XImage createImage(int width, int height, InstanceFactory<? extends XImage> factory) {
XImage xImg = factory.newInstance();
xImg.createImage(width, height);
return xImg;
}
//メインでは...
XImage xImg = createImage(100, 200, factory);
dispSize(xImg);
この方法なら、すべて共通のコードで書けることがわかるだろう。もちろんこれ以外の XImage インターフェイスを持ったインスタンス生成インターフェイスを定義すれば、そのままオブジェクトを入れ替えても、使えるという利点もある。
配列などもインターフェイスに定義可能だ。既存の InstanceFactory 少し改造してみよう。
●インスタンス生成用のインターフェイス(InstanceFactory)を配列対応にしてみる
public interface InstanceFactory<T> {
public T newInstance();
public T[] newInstance(int length);
public T[][] newInstance(int col, int row);
}
●Android 版 インスタンス生成用のインターフェイス(InstanceFactory)配列対応 実装
InstanceFactory<XImage> factory = new InstanceFactory<XImage>() {
@Override
public XImage newInstance() {
return new AndroidImage();
}
@Override
public XImage[] newInstance(int length) {
XImage[] images = new XImage[length];
for (int i = 0; i < length; i++) {
images[i] = new AndroidImage();
}
return images;
}
@Override
public XImage[][] newInstance(int col, int row) {
XImage[][] images = new XImage[row][col];
for (int j = 0; j < row; j++) {
for (int i = 0; i < col; i++) {
images[j][i] = new AndroidImage();
}
}
return images;
}
};
●Applet 版 インスタンス生成用のインターフェイス(InstanceFactory)配列対応 実装
InstanceFactory<XImage> factory = new InstanceFactory<XImage>() {
@Override
public XImage newInstance() {
return new AppletImage();
}
@Override
public XImage[] newInstance(int length) {
XImage[] images = new XImage[length];
for (int i = 0; i < length; i++) {
images[i] = new AppletImage();
}
return images;
}
@Override
public XImage[][] newInstance(int col, int row) {
XImage[][] images = new XImage[row][col];
for (int j = 0; j < row; j++) {
for (int i = 0; i < col; i++) {
images[j][i] = new AppletImage();
}
}
return images;
}
};
実際の利用において、画像生成が少々面倒だと思ったら、コンストラクタを付け加えるのも良いだろう。画像生成用のコンストラクタと InstanceFactory を改造した XImageFactory インターフェイスを作ってみる。
●Android 版 画像ラッパークラス(AndroidImage)に画像生成のコンストラクタを付け加える
public final class AndroidImage implements XImage {
private Bitmap image;
//コンストラクタ
public AndroidImage() {
}
//画像生成のコンストラクタ
public AndroidImage(int width, int height) {
createImage(width, height);
}
@Override
public void createImage(int width, int height) {
this.image = Bitmap.createBitmap(width, height, Config.ARGB_8888);
}
@Override
public int getWidth() {
return image.getWidth();
}
@Override
public int getHeight() {
return image.getHeight();
}
}
●Applet 版 画像ラッパークラス(AppletImage)に画像生成のコンストラクタを付け加える
public final class AppletImage implements XImage {
private BufferedImage image;
//コンストラクタ
public AppletImage() {
}
//画像生成のコンストラクタ
public AppletImage(int width, int height) {
createImage(width, height);
}
@Override
public void createImage(int width, int height) {
this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
}
@Override
public int getWidth() {
return image.getWidth();
}
@Override
public int getHeight() {
return image.getHeight();
}
}
●インスタンス生成用のインターフェイスを画像生成用に改造する(XImageFactory)
public interface XImageFactory<T> {
public T newInstance(int width, int height);
public T[] newInstance(int width, int height, int length);
public T[][] newInstance(int width, int height, int col, int row);
}
XImageFactory インターフェイスはよく使うのであれば、匿名ではなく、クラスに実装しても良い。
●Android 版画像生成用のインターフェイス(XImageFactory)をクラスに実装(AndroidImageFactory)
public final class AndroidImageFactory implements XImageFactory<AndroidImage> {
//コンストラクタ
public AndroidImageFactory() {
}
@Override
public AndroidImage newInstance(int width, int height) {
return new AndroidImage(width, height);
}
@Override
public AndroidImage[] newInstance(int width, int height, int length) {
AndroidImage[] images = new AndroidImage[length];
for (int i = 0; i < length; i++) {
images[i] = new AndroidImage(width, height);
}
return images;
}
@Override
public AndroidImage[][] newInstance(int width, int height, int col, int row) {
AndroidImage[][] images = new AndroidImage[row][col];
for (int j = 0; j < row; j++) {
for (int i = 0; i < col; i++) {
images[j][i] = new AndroidImage(width, height);
}
}
return images;
}
}
●Applet 版画像生成用のインターフェイス(XImageFactory)をクラスに実装(AppletImageFactory)
public final class AppletImageFactory implements XImageFactory<AppletImage> {
//コンストラクタ
public AppletImageFactory() {
}
@Override
public AppletImage newInstance(int width, int height) {
return new AppletImage(width, height);
}
@Override
public AppletImage[] newInstance(int width, int height, int length) {
AppletImage[] images = new AppletImage[length];
for (int i = 0; i < length; i++) {
images[i] = new AppletImage(width, height);
}
return images;
}
@Override
public AppletImage[][] newInstance(int width, int height, int col, int row) {
AppletImage[][] images = new AppletImage[row][col];
for (int j = 0; j < row; j++) {
for (int i = 0; i < col; i++) {
images[j][i] = new AppletImage(width, height);
}
}
return images;
}
}
●インスタンス生成インターフェイスの実装クラスを生成(Android 版)
XImageFactory<? extends XImage> factory = new AndroidImageFactory();
●インスタンス生成インターフェイスの実装クラスを生成(Applet 版)
XImageFactory<? extends XImage> factory = new AppletImageFactory();
●メインコードでは...
//インスタンス生成(100 x 200 で画像を生成)
XImage xImg = factory.newInstance(100, 200);
dispSize(xImg);
実装クラスの左辺は XImageFactory<? extends XImage> となってるが、実装クラスの型でも良い。ここでは見た目上、 XImage の派生クラスと解りやすいように表記した。
ここまで来れば、もうメインコードはほとんど共通化できる。new 演算子は極力使わず、factory のインターフェイスを使って、インスタンスを生成するコードで書いて置けば、プラットフォーム依存の少ないコードになることが分かるだろう。新たにプラットフォームが加わった場合も、その画像ラッパークラスを作れば、そのまま使える。factory はメソッドの引数にもできるので、色々とやってみると良いだろう。
●factory をメソッドの引数にする(あまりコードに意味はない)
public XImage[][] createImages(int width, int height, int col, int row, XImageFactory<? extends XImage> factory) {
return factory.newInstance(width, height, col, row);
}
以下は、実際の画像オブジェクトラッパークラスを使ったデモ。Applet 版と Android 版の2種類作ってあるが、どちらもメイン部分は同じコードで書かれている(というより同じコードを参照している)。
サンプルデモ:つかさんパズル
Applet 版のサンプル (PC[IE]でアクセス)
Android 版のサンプル (Android2.2以降でアクセス)
(解説) Android と Applet の互換ってできるもんだね
(関連記事)
【Android】【Applet】【Java】interface を使って独自のラッパークラスを作る
【Android】【Applet】【Java】interface と abstract の使い方・違いとは~簡単なフレームワークを作って、考えてみる
【Java】interface を使って簡単なコールバック機能を作る
【Android】【Java】clone() を使ったオブジェクト複製
- 関連記事
-
-
【Java】8クイーンを解く[8クイーン問題]
-
【Java】プリム法[最小全域木] (Prim's algorithm, Minimum Spannig Tree)
-
【Android】【Applet】【Java】interface を使ってインスタンスを生成する
-
【Java】平衡三進数変換をする
-
【Java】ワーシャル-フロイド法[全点対間最短経路] (Warshall-Floyd algorithm, All Pairs Shortest Path)
-
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/129-223f6c80
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |