こんにちは、
デザインパターンを勉強しており、クラスにファクトリーパターンあるいは、アブストラクトファクトリーパターンを適用したいと思っています。
ConfigDataというクラスがあり、この中には、spec1, spec2, spec3, DateFile1, DateFile2というクラスを持っています。 それぞれ、もとはファイル形式で、このConfigDataクラスで、newをして、パスを渡して、読み込んで、オブジェクトとして保持しています。
そこで、質問なのですが、このようなクラスにファクトリークラスを適用する場合、どうするのがいいのでしょうか?現在は下記のように少ししてみました。
public class ConfigData
{
Spec1 spec1;
Spec2 spec2;
Spec3 spec3;
DateFile1 df1;
DateFile2 df2;
public void importSpec(){
SpecFactotry[] factory = new SpecFactpry[3];
factory[0] = new Spec1Factory();
factory[1] = new Spec2Factory();
factory[2] = new Spec3Factory();
spec1 = (Spec1) factory[0].create(path);
spec2 = (Spec2) factory[1].create(path);
spec3 = (Spec3) factory[2].create(path);
}
}
もともとは、importSpecのところで、ただnewをそれぞれしていました。
このような場合、ファクトリークラスを適用する必要はないのでしょうか?
No.1ベストアンサー
- 回答日時:
>このような場合、ファクトリークラスを適用する必要はないのでしょうか?
システムによりけりですが、基本的にはシステムを疎結合に保つことで
拡張性や保守性が上がるので、意識はすると良いかと思います。
最近はDIコンテナが変わりにインスタンス生成してくれたりするので
あまりファクトリーメソッドを使ったことがないのですが、
適用したら下記のようになりますかね?
(間違っていたらどなかたご指摘お願いします)
※DataFileとSpecの関連が分からなかったので、DataFileは無視してます。
【ファクトリーメソッドだけ適用】
まずは生成対象オブジェクト(Spec1,2,3など)を疎に扱うために
それぞれ同一のインタフェースを実装する必要があるかと思います。
public interface Spec {
// Spec に関する公開処理
}
public class Spec1 implements Spec {...
public class Spec2 implements Spec {...
public class Spec3 implements Spec {...
これらを利用する側は、Spec1,2,3などの具体的なクラスは意識せず
Specインタフェースのみ意識するように作ります。
そのため、ファクトリーメソッドでSpec型で返すようにしておきます。
Spec s = createSpec(); // 1, 2, 3 のいずれかが返る。
s.process(); // 1,2,3を意識させず、疎に扱う。インスタンスの動作にまかせる。
createSpec() メソッドは、何らかの条件で1,2,3のいずれかの
インスタンスを返したりするようにしておく。
(この createSpec() がファクトリーメソッド)
こうしておくと利用側は、例えば Spec4,5 が増えても修正不要。
修正が必要なのはファクトリーメソッドのみとなります。
(ご質問の例では、Spec1,2のキャストを行っているので、クラスが増えると対応が必要)
【アブストラクトファクトリーも適用】
上記に加えて、ファクトリー自身も抽象化します。
public interface SpecFactory {...
public class Spec1Factory implements SpecFactory {...
public class Spec2Factory implements SpecFactory {...
public class Spec3Factory implements SpecFactory {...
Factory(工場)自身も抽象化し、それぞれSpec1やSpec2だけに関連した処理をまとめます。
利用する側は、SpecFactory インタフェースとして扱うことで、
それぞれに特化した処理が施された結果で受け取ることができます。
ご質問の例では、Spec のみ扱っているのでファクトリーメソッド適用の段階で止めても良い気がしますが、例えば「Spec1 と DataFile1」、「Spec2 と DataFile2」がそれぞれ紐付くのであれば、適したファクトリーにその組み合わせでの処理を記述しておけば、
利用する側は「Spec1 と DataFile2」などの組み合わせの間違いを防ぐことができます。
この回答への補足
DateFile1とSpecは特に関係はありません。実はそれぞれ、エクセルファイルだったり、テキストだったりして、それを読み込んでいます。spec1から3までは、エクセルファイルで若干、書かれている内容が違ったりしています。データファイルはテキストファイル(ini)を読み込んでデータを保持しています。
私は、Specを抽象クラスにして、1、2、3をその子にしました。というのはSPECクラスにおいて、読込先のファイルパスを保持していたり、ファイル名の部分は共通でもっておくべくかなと思ったので。インターフェースにして、外部からパス名をもらったほうがいいのでしょうか。
No.2
- 回答日時:
>インターフェースにして、外部からパス名をもらったほうがいいのでしょうか。
大事なのは利用側が具象型(Spec1,2,3)ではなく、共通型(Spec)で扱えるということなので、抽象クラスでも問題ありません。
ただ、Javaでは多重継承ができないので私は以下の点に気を付けています。
1.「継承」は基本的に is-a の関係とする。「インタフェース」は特定の機能を付加するもの。
例えばゲームプログラミングなどであれば、Character(親)←Player(子)/Enemy(子)のように、キャラクター=プレイヤー、キャラクター=敵のような関係であれば「継承」を利用します。
ただ、「移動可能」「攻撃可能」「魔法可能」のような「機能」を付加する場合は、「Movable」「Attackable」「Magicable」など「* + able」の命名などで「インタフェース」を利用しています。
2.ただし、インタフェースには処理が記述できない(Java7までは)ので、上記のようなインタフェースを実装した別の「具象クラスX」を用意し、それを「委譲(has-a)」という形でフィールドに保持し、共通処理はその「具象クラスX」にまかせます。
その際、保持しているクラス自身も上記インタフェースを実装しておきます。(デザインパターンで言うと、Compositeパターンになるでしょうか。委譲を利用したAdapterパターンでも良いと思います)
(参考) (h)ttp://www.techscore.com/tech/DesignPattern/Composite.html/
(参考) (h)ttp://www.techscore.com/tech/DesignPattern/Adapter/Adapter2.html/
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 数学 a1,a2, a3をベクトル空間Vのベクトルとする。a1+a2,a2+a3,a3+a1が一次独立のと 2 2022/10/02 15:55
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- 英語 TOEIC公式問題集7にある英語で質問があります。 以下の文です。 Have you heard f 2 2022/08/02 06:51
- Excel(エクセル) エクセルの式を教えて下さい 2 2022/04/10 13:16
- Java java final 1 2022/06/10 22:49
- C言語・C++・C# c言語でユーザ関数を利用して複素数のべき乗と絶対値の数列を計算するプログラムが作りたいです。 3 2023/01/29 22:13
- 数学 座標平面上に放物線 C1: y=ax^2+b^x+4 がある。 C1と直線 y=1に関して対称で あ 1 2023/07/16 22:27
- C言語・C++・C# クラスのメンバ変数を基準に並べ替えをしたい 5 2022/12/25 17:40
- Excel(エクセル) Excelについて質問があります。 関数の数値入力についてなのですが、 b1にー c1に数値 がある 2 2023/05/28 12:30
- Excel(エクセル) エクセル関数について 2 2022/05/30 14:36
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C#にて別クラスの関数を使いたい
-
Java
-
c++,ある関数のクラスから別の...
-
クラス間でのデータ参照
-
関数内の変数に<summary>コメン...
-
プログラムの変数名にするとど...
-
VisualC++でクラスのヘッダーフ...
-
命名規約について
-
java-別クラスの変数の使い方を...
-
ClassLoader.getSystemResource...
-
visual studioのデザイナ画面で...
-
無名パッケージからのインポート
-
C#でほかのファイルにある自作...
-
a href="..." とServlet
-
Java リフレクションについて
-
Javaでのジェネリクス型パラメ...
-
import と extends について
-
javaでメインクラスが見つから...
-
アブストラクトとインターフェ...
-
範囲外の数値を代入したらエラ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数内の変数に<summary>コメン...
-
クラス間でのデータ参照
-
c++,ある関数のクラスから別の...
-
範囲外の数値を代入したらエラ...
-
C#にて別クラスの関数を使いたい
-
C#でほかのファイルにある自作...
-
C++でfriendクラスにしているの...
-
java-別クラスの変数の使い方を...
-
親クラスから子クラスへアクセス。
-
構造 他のクラスの構造体を別...
-
ひとつのファイルにクラスは1つ?
-
Java
-
import と extends について
-
継承したクラス側のクラス名の取得
-
Java リフレクションについて
-
C#のクラスライブラリでメッセ...
-
SwingでgetContentPaneのエラー...
-
アップキャスト、ダウンキャス...
-
C# インターフェイスの実装
-
visual studioのデザイナ画面で...
おすすめ情報