≪第8回・第10回≫
全てのファクトリパターンは、 『オブジェクトの作成をカプセル化することで 具象クラスへの依存度を減らして 抽象へのコーディングを促進することができる』お __ .-´ ``ヽ / ⌒ `ヽ / `ヽ ヽ (( / (●) ヽ |::⌒(__ (● ) | ヽ 人__) ⌒:::: | ヽ(__ン | 人 / | | / _ノ ノノ | 「オブジェクトの作成」・「カプセル化」 「具象クラスへの依存」・「抽象へのコーディング」 どれも腹に落ちてくる言葉じゃないから、たとえ話で 教えてほしいものだお。 「人に上手に説明ができる人は抽象化がちゃんとできている」 っていったのはアーキテクトだお。 __ /´ ``ヽ /:::::::::::::::: \ `ヽ /:::/::::::::<● > `ヽ (( / <●>::::::::::⌒ ) | ⌒(_人__) ノ | | ヽ )vvノ: / ノノ ヽ (__ン 人 人 \ / おめぇは前回の犯行で警察のご厄介になってたんじゃねぇのか? / ̄ ̄\ ( ;;;;( / _ノ ヽ\ ) ;;;;) | ( ○) (○)/;;/ . | (__人__) l;;, | ∩ ノ)━・'/ . | / ノ´ } . ヽ / / } ヽ/ / ノ
今回のデザインパターンである、ファクトリのパターンの内、残しているのはアブストラクトファクトリです。シンプルファクトリ、ファクトリメソッド、アブストラクトファクトリとも、インスタンスの生成を疎結合に実装されるもので、今回のソースの例で言うと、Gameクラスとこれを使用するGameCompany型のクラスの依存を減らすものです。
以前やったファクトリメソッドでは、「継承」を使ってインスタンスの生成が決定されていました。GameCompanyを継承するサブクラスがどんなゲームクラスを生成するかを決定するというものです。アブストラクトファクトリでは、コンポジションを使ってゲームクラスを生成します。コンポジションとは、ストラテジーパターンでもやったような仕組みで、継承を使って処理の拡張を行うのではなく、適切な振舞いを「オブジェクト」で構成することをさします。というわけで、どのファクトリパターンもインスタンスの生成を行うものだということにはまったく変わりありません。
・createElement
・createDocumentFragment
・createComment
・createProcessingInstruction
・createAttribute
・createEntityReference
こんな風に一連の生成メソッドが用意されていました。
アブストラクトファクトリの特徴は、なんといっても「一連の」オブジェクトを作ることです。が、1つ1つのインターフェイスを紐解くと、ファクトリメソッドと変わりないことに気づきます。当然といえば当然なのですが、インスタンスを生成するインターフェイスはひとつである必要はありません。となると、クライアントが必要なプロダクトがグループから構成されているようなプロダクトを使用する場合に使うといいかもしれません。それは、上記のようにDOMだったりします。
以前やったファクトリメソッドでは、「継承」を使ってインスタンスの生成が決定されていました。GameCompanyを継承するサブクラスがどんなゲームクラスを生成するかを決定するというものです。アブストラクトファクトリでは、コンポジションを使ってゲームクラスを生成します。コンポジションとは、ストラテジーパターンでもやったような仕組みで、継承を使って処理の拡張を行うのではなく、適切な振舞いを「オブジェクト」で構成することをさします。というわけで、どのファクトリパターンもインスタンスの生成を行うものだということにはまったく変わりありません。
public class Test {
public static void main(String[] args) {
// ゲーム会社を指定して
NiconicoGameCompany inst = new NiconicoGameCompany();
// ソフト名でオーダーします。
Game myGame = inst.orderGame( "やるおの大冒険" );
/*
出力:
アクションゲームの製作
アクションゲームのテスト
アクションはパッケージがかっこよくないと!
*/
}
}
// アブストラクトファクトリ
interface MyAbstractFactory {
public Members createProjectMembers();
public Budget createBudget();
public PackageBox createPackageBox();
};
// ニコニコゲームファクトリ
class NiconicoFactory implements MyAbstractFactory {
// 具象クラスがプロダクト群を決定する。
public Members createProjectMembers(){
return new NiconicoMembers();
}
public Budget createBudget(){
return new HugeBudget();
}
public PackageBox createPackageBox(){
return new NicoNicoPackage();
}
}
// アブストラクトプロダクト
interface Members {}
interface Budget {}
interface PackageBox {}
// 具象プロダクト
class NiconicoMembers implements Members {}
class HugeBudget implements Budget {}
class NicoNicoPackage implements PackageBox {}
// ゲーム製作会社スーパークラス
abstract class GameCompany {
public Game orderGame( String name ){
// サブクラスに作成するゲームを決定させる
Game gameInst = createGame( name );
gameInst.prepare();
gameInst.produce();
gameInst.checkProduct();
gameInst.onPackage();
return gameInst;
}
// ファクトリオブジェクトから受け取ったcreateGameメソッド
abstract Game createGame( String name );
}
class NiconicoGameCompany extends GameCompany {
// サブクラスが作成するゲームを決定する
Game createGame( String name ){
// ニコニコゲーム会社用ファクトリを生成する
MyAbstractFactory fctryInst = new NiconicoFactory();
Game gameInst = null;
if( name.equals( "やるおの大冒険" ) ){
// ファクトリを渡してゲームを構成する
gameInst = new ActionGame( fctryInst );
}
else if( name.equals( "ニコニコクロニクル" ) ){
// ファクトリを渡してゲームを構成する
// gameInst = new RPGGame( fctryInst );
}
// ほかにもたくさん。
return gameInst;
}
}
// ゲームクラス。
abstract class Game {
MyAbstractFactory factory;
String category;
// ファクトリのプロダクト:開発メンバー
Members membersInst;
// ファクトリのプロダクト:開発予算
Budget prjBudget;
// ファクトリのプロダクト:パッケージ
PackageBox packageBox;
abstract void prepare();
void produce(){ System.out.println( category + "ゲームの製作" ); }
void checkProduct(){ System.out.println( category + "ゲームのテスト" ); }
void onPackage(){ System.out.println( category + "ゲームのパッケージ" );}
}
// ゲームクラスを継承して実装
class ActionGame extends Game {
ActionGame( MyAbstractFactory param ){
this.factory = param;
this.category = "アクション";
}
// ファクトリを使ってゲームを準備する。
void prepare(){
membersInst = factory.createProjectMembers();
prjBudget = factory.createBudget();
packageBox = factory.createPackageBox();
}
void onPackage(){
System.out.println( "アクションはパッケージがかっこよくないと!" );
}
}
と、サンプルソースを書いてみました。今回のサンプルソースのファクトリのプロダクトはGameクラスではないことにご注意ください。アブストラクトファクトリはDOM(Document Object Model)で使われているようです。(wikiにありました)・createElement
・createDocumentFragment
・createComment
・createProcessingInstruction
・createAttribute
・createEntityReference
こんな風に一連の生成メソッドが用意されていました。
アブストラクトファクトリの特徴は、なんといっても「一連の」オブジェクトを作ることです。が、1つ1つのインターフェイスを紐解くと、ファクトリメソッドと変わりないことに気づきます。当然といえば当然なのですが、インスタンスを生成するインターフェイスはひとつである必要はありません。となると、クライアントが必要なプロダクトがグループから構成されているようなプロダクトを使用する場合に使うといいかもしれません。それは、上記のようにDOMだったりします。
なんだかデザインパターンとかいって 実装のしかたをあーだこーだと縛って コーディング規約みたいに感じてきたお ____ / \ ( ;;;;( / _ノ ヽ__\) ;;;;) / (─) (─ /;;/ | (__人__) l;;,´ / ∩ ノ)━・'/ ( \ / _ノ´.| | .\ " /__| | \ /___ / デザインパターンを適用することで 高度な実装ができるんじゃなかったのかお! ノ L____ ⌒ \ / \ / (○) (○)\ / (__人__) \ | |::::::| | \ l;;;;;;l /l!| ! / `ー' \ |i / ヽ !l ヽi ( 丶- 、 しE |そ ドンッ!! `ー、_ノ ∑ l、E ノ < レY^V^ヽl まったく!アーキテクトのやろう 「お前の実装を見直してどんなクラスに どれだけ依存しているか数えてみろ」 ____ / \ /\ キリッ . / (ー) (ー)\ / ⌒(__人__)⌒ \ | |r┬-| | \ `ー'´ / ノ \ /´ ヽ | l \ ヽ -一''''''"~~``'ー--、 -一'''''''ー-、. ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒)) だっておwwwwwwwwww ____ /_ノ ヽ、_\ バン バン ミ ミ ミ o゚((●)) ((●))゚o ミ ミ ミ /⌒)⌒)⌒. ::::::⌒(__人__)⌒:::\ /⌒)⌒)⌒) | / / / |r┬-| | (⌒)/ / / // | :::::::::::(⌒) | | | / ゝ :::::::::::/ | ノ | | | \ / ) / ヽ / `ー'´ ヽ / / | | l||l 从人 l||l l||l 从人 l||l ヽ -一''''''"~~``'ー--、 -一'''''''ー-、 ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒)) 依存してるのはアーキのほうだお スーパーハカーのおいらの腕に依存しないでほしいお ____ /⌒ ⌒\ ホジホジ /( ●) (●)\ /::::::⌒(__人__)⌒::::: \ | mj |ー'´ | \ 〈__ノ / ノ ノ はいはい依存依存。ハカーハカー。 とっととデバッグしろこのスカーハパー / ̄ ̄\ / _ノ \ | ( ●)(●) . | (__人__)____ | ` ⌒/ ─' 'ー\ . | /( ○) (○)\ . ヽ / ⌒(n_人__)⌒ \ ヽ |、 ( ヨ | / `ー─- 厂 / | 、 _ __,,/ \≪第8回・第10回≫




コメント (2)
あの、MyAbstractFactoryのサンプルソースは…
投稿者: DO | 2008年04月29日 03:50
日時: 2008年04月29日 03:50
DOさんこんにちは!
ご指摘ありがとうございます。ファクトリのサンプルがなければなんのサンプルにもなりませんでしたね。読んでいただいたのに申し訳ございません。
ソースを修正して載せておきました。
投稿者: ひげもじゃ | 2008年04月29日 13:07
日時: 2008年04月29日 13:07