質問
に努めていく工場でのパターンの作成はMainModeやTestMode私のプログラム。をコードした使用これらのオブジェクトを作成するた
play = (isMode) ? new MainMode(numberRanges, numberOfGuesses) :
new TestMode(numberRanges, numberOfGuesses, randNo());
私のゲーム(遊び)のいずれかをMainModeオブジェクトまたはTestModeオブジェクトによってはboolean値(isMode).ご覧のとおり私を追加する値の入っTestModeオブジェクト(randNo()).この値は内TestModeするユーザーの入力に自分の乱数"、内MainModeこのコンストラクタをランダムに生成されます。このプログラムの両方MainModeとTestModeのサブクラスの抽象クラスです。
今は違反の原因となるため使用しないこと、工場パターンは私の迷っTestModeコンストラクタが必要で余分なオブジェクト、I amご不明の場で必要となるであろうこと。また新工場で必要な新しいクラスは、その名GameFactoryはModeFactoryなされるようになっています。
そこまで行くのか。
編集: ここでの問題は、上記のコードは私のGUIの値numberRanges,numberOfGuessesのrandNo()メソッドです。作りたい場合は、ファクトリクラスができない、それぞれの値によっrandNo()起動します。こちらは自randNo()メソッドがあります。
private int randNo() {
boolean isValidNumber = true;
int testRandomNum = 0;
while(isValidNumber) {
try {
testRandomNum = Integer.parseInt(JOptionPane.showInputDialog("Enter Random Number"));
isValidNumber = false;
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Sorry, but the number you entered was invalid");
}
}
return testRandomNum;
}
問題は場していただくためにrandNo()このJOptionPane.としてのGUIとロジックは別です。GUIは、GUIパッケージを他のコードの論理パッケージです。
解決
場合がありますので、ご注意その他の回答が言説明、工場な記述する GOFパターン工場.
今は違反の原因となるため使用しないこと 工場のパターンは私の不 私のTestModeコンストラクタが必要です 余分なオブジェクトは、私は迷う る必要があること。
、こちらをクリックして下さい思いのこのようになっております:MainModeはTestMode、一つのことは特別なものです。に特別なもので、 無視する 指定された数を確保しっかせとなります。このように考えでMainModeることになります。
または、以外の場合は、乱数の発生源,MainModeとTestModeは異なり、そのまえに考えるのかもしれま因子との類似性を一つのクラスでは、つの戦略の算定上のランダムます。一つの戦略が実際にランダムになると、きせき、ランダムな範囲のみの1の値です。
もしようがその他の違いMainModeとTestMode休TestMode出力特のデバッグシステム.出あります。
まだ要因"がどのような供給していま乱数の発生源から"を試験またはゲームのために。これらの 直交 です。
そこで、私たちは今、知るほか、などの"モードではランダムネス戦略です。その後、例えば、"のように、標準プランダムなんですがランダムに上がれます♪※数に限りがございで代替することはできないよかせとなります。
は試験の範囲のrandomsにわたって制約されることになれだけだと、常に交互に行からゼロを返します各電話が次の値の一部VecrtorはIterator.
を使用しておりますのでGOF戦略パターンの乱数の発生源戦略
interface RandomStrategy {
public double random();
}
public class NotSoRandom implements RandomStrategy {
private double r;
public NotSoRandom( final double r ) { this.r = r; }
public double random() { return r; }
}
public class PlatformRandom implements RandomStrategy {
public double random() { return Math.random(); }
}
今いる場合、全体のアプリのみを作成しつつあるモードでは、必要はありません、工場をご利用の場合に必要なものを同一クラスタイプと、工場は実はただの戦略の作成、適度(字)クラスです。
生産コードを使用しました工場をしているのか教えてください汎用クラスを生成するものは、"どれだけ作成のためのサブクラスを作成していただくための工場になる。
今作工場でのパターンのモードに切り替わり、これは驚くほどと同様の戦略パターン:
abstract class Mode() {
private RandomStrategy r;
public Mode( final RandomStrategy r ) { this.r = r; }
// ... all the methods a Mode has
}
public class MainMode implements Mode {
public MainMode( final RandomStrategy r ) { super(r); }
}
public class TestMode implements Mode {
public TestMode( final RandomStrategy r ) { super(r); }
}
interface ModeFactory{
public Mode createMode( final RandomStrategy r );
}
public class MainFactory() {
public Mode createMode( final RandomStrategy r ) {
return new MainMode(r);
}
}
public class TestFactory() {
public Mode createMode( final RandomStrategy r ) {
return new TestMode(r);
}
}
今までのに関する知識はどのくらいの工場でのパターンや戦略パターンにどのように類似の形状が異なる方がいたりして使われてい:工場のパターンは、オブジェクトCreationalを返しますオブジェクトを使用する必要戦略は、オブジェクトの行動、インスタンスは、通常は明示的に参照されるインスタンス、封止アルゴリズム.しかし、構造という大きさでありながらできていることが分かります。
編集:OP問、コメントをどう埋め込むっGUI?"
でも、この所属のGUIプログラムを除き、そのモードになります。んのConcreteStrategyでの優先工場の一部の設定ルーチンは、あるかを決定するために基づく利用のコマンドライン引数またはconfigファイルです。基本的にはいを選択し、正しい工場にもご協力お願いいたしますを選択する正しいクラスオリジナル。 もう一度言いますが、ご利用いただけるものをつ何かする必要がなくなり、より快適な工場工場が大量生産または作家の関連コンクリートの種類がこの範囲を超えてこい。
(いいゲームは、ユーザーが選択でき、コマンドラインか否かの戦闘ロボットやドラゴンズ;しいインスタンスを生成するOpponentFactoryを産生する相手(インターフェース)、導出クラスでRobotOpponentとDragonOpponent、その工場の一部のゲームspawnsNewOpponent().同様に、ユーザが選択で勇または臆病な相手に、私たちの設定として戦略です。まんが大きく変化しつつあり戦略インスタンスとして戦略が通常は例外:(無国籍やシングルトン).)
static int main( String[] args ) {
// setup game world
final RandomStrategy r = "random".equals(args[0])
? new PlatformRandom() : new NotSoRandom( Integer.intValue(args[0]) ) ;
// notice the simlarity to the code you originally posted;
// we factored out how to achieve "randomness" as a Strategy.
// now we will use our Strategy to setup our Factory;
final ModeFactory f = "test".equals(args[1])
? new TestFactory(r) : new MainFactory(r);
// also similar to your code
// we've just added an extra level of indirection:
// instead of creating a Mode, we've created an object that can create Modes
// of the right derived type, on demand.
// call something that uses our factory
functionThatRunsameAndNeedstoProduceModesWhenevertNeedsTo( f );
}
他のヒント
工場の全体のポイントは、それが適切にあなたのゲームを作成するために必要な状態を持つべきであるということです。
だから私はこのような工場を建設します
public class GameFactory {
private boolean testMode;
public GameFactory(boolean testMode) {
this.testMode = testMode;
}
public Game getGame(int numberRanges, int numberOfGuesses) {
return (testMode) ? new MainMode(numberRanges, numberOfGuesses) :
new TestMode(numberRanges, numberOfGuesses, getRandom());
}
private int getRandom() {
. . . // GUI code here
}
}
今すぐあなたのアプリでsomwhereこのファクトリを初期化し、ゲームを作成する必要があるものは何でもコードにそれを渡すことができます。このコードは、今、それが何であるかのモードを心配する必要があり、余分なランダムのparamsを渡すことはありません - それは、ゲームを作成するためによく知られているインターフェースを使用しています。すべての必要な状態がGameFactoryオブジェクトによって内在化されます。
のように気にいらを試してみて、
abstract class ModeFactory {
public static Mode getMode(isMode, numberRanges, numberofGuesses) {
return isMode ? new MainMode(numberRanges, numberofGuesses) : new TestMode(numberRanges, numberOfGuesses, randNo());
}
public static Mode getMode(isMode, numberRanges, numberofGuesses, someNumber) {
return isMode ? new MainMode(numberRanges, numberofGuesses) : new TestMode(numberRanges, numberOfGuesses, someNumber);
}
}
クラスは、単に初期化を停止するように抽象的です。あなたは、最終的な使用し、プライベートコンストラクタを作成するために、それを修正することができます。
あなたのコードは、おそらくファクトリパターンに変更することができます。
のような何かます:
public static Mode createMode(boolean isMainMode)
{
if(isMainMode) return new MainMode(...);
return new TestMode(...);
}
どこかに賢明(この1つは、多分静的ModeFactoryトリッキーである)
この方法を置きこれは
MainModeとテストモードは、同じタイプのサブタイプである(サブクラスまたはモードインタフェースを実装する)ことを前提としていこれで、すべてのプレーが関係していModeFactory.createMode(...)を呼び出して、適切なブール値を渡すことです。
(OP更新に応答して)編集:
あなたのrand()は、実際のコンストラクタが呼び出される前に評価され、それがGUIを提供します。あなたが自分自身を活性化することにより、何を意味するということですか?
あなたはモードについての決定を作りたい設計上の決定をしなければなりません。あなたはGUIを持っていて、モデルを持っている場合、あなたがファクトリメソッドを呼び出す前に、ランダム生成(ポップアップ)への呼び出しが必要であるか否かを知るためにGUIを設計することが好ましいこと、およびその後に乱数を渡すかもしれませんファクトリメソッドとそれだけで正しいコンストラクタを選んでみましょう。
(モデルはあなたのGUIを呼び出して)他の方法の周りにそれを持ってトリッキー、おそらく悪い考えです。
interface ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses);
}
class MainModeFactory implements ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses) {
return new MainMode(numberRanges, numberOfGuesses);
}
}
class TestModeFactory implements ModeFactory {
Mode createMode(int numberRanges, int numberOfGuesses) {
return new TestMode(numberRanges, numberOfGuesses, randNo());
}
}
...
play = modeFactory.createMode(numberRanges, numberOfGuesses);
起動時にあなたがプレイを作成する必要がどこにそれを渡して、適切なモードファクトリを作成だからます。
非常に単純に、のいつもあなたが他の「モード」のためのいくつかのパラメータを持っている場合は、単一のパラメータに、それらをカプセル化し、null
を送った場合にパラメータが使用されていない、のパラメータを使用します。
あなたはあなたのためだけに与えられた名前のクラスを作成するファクトリメソッド、後にある場合は、これを試してください:
public static MyInterface createClass(String name) throws IllegalAccessException,
InstantiationException, ClassNotFoundException {
try {
Class myClass = Class.forName(name);
MyInterface myObj = (MyInterface) myObj.newInstance();
return myObj;
} catch (ClassNotFoundException ex) {
logger.error("Could not find a class {}", name);
throw ex;
} catch (InstantiationException e) {
logger.error("Class must be concrete {}", name);
throw e;
} catch (IllegalAccessException e) {
logger.error("Class must have a no-arg constructor {}", name);
throw e;
}
}
だけ楽をしたいでく工場を返しますオブジェクトの抽象クラスまたはインターフェース(theyr実装を行う担当者に役立ちました。のファクトリメソッドましdeside、実装者が決定を選択します。すを選択するabstractクラスなので、実践できる共通の論理ではうその他の方法で未実装(宣言文いようにコンクリートdescendersの実装によってtheyrます。この工場デザインパターン:
public class GridManagerFactory {
public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){
AbstractGridManager manager = null;
// input from the command line
if(args.length == 2){
CommandLineGridManager clManager = new CommandLineGridManager();
clManager.setWidth(Integer.parseInt(args[0]));
clManager.setHeight(Integer.parseInt(args[1]));
// possibly more configuration logic
...
manager = clManager;
}
// input from the file
else if(args.length == 1){
FileInputGridManager fiManager = new FileInputGridManager();
fiManager.setFilePath(args[0]);
// possibly more method calls from abstract class
...
manager = fiManager ;
}
//... more possible concrete implementors
else{
manager = new CommandLineGridManager();
}
manager.setLifecicleAlgorithm(lifecicleAlgorithm);
return manager;
}
}
のcommounロジックの抽象クラスは、入手可能なdescenders:
public abstract class AbstractGridManager {
private LifecicleAlgorithmIntrface lifecicleAlgorithm;
// ... more private fields
//Method implemented in concrete Manager implementors
abstract public Grid initGrid();
//Methods common to all implementors
public Grid calculateNextLifecicle(Grid grid){
return this.getLifecicleAlgorithm().calculateNextLifecicle(grid);
}
public LifecicleAlgorithmIntrface getLifecicleAlgorithm() {
return lifecicleAlgorithm;
}
public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) {
this.lifecicleAlgorithm = lifecicleAlgorithm;
}
// ... more common logic and geter-seter pairs
}
のコンクリートのapiだけで、次のメソッドを実装しが宣言された抽象的な:
public class FileInputGridManager extends AbstractGridManager {
private String filePath;
@Override
public Grid initGrid() {
return this.initGrid(this.getFilePath());
}
public Grid initGrid(String filePath) {
List<Cell> cells = new ArrayList<>();
char[] chars;
File file = new File(filePath); // for ex foo.txt
// ... more logic
return grid;
}
}
受信機のAbstractGridManagerと呼んだのではなかったかの方法で彼のロジック、実施の具体的なdescenders(partuallyの抽象クラスメソッド)などのコンクリート実行った。これはもう逆転の制御依存性射出