0

プロパティをテキスト ファイルに書き込む必要がある複数のクラスがあります。各クラスには異なるプロパティがあるため、それぞれ異なるアルゴリズムを記述する必要があります。これに戦略パターンを使用しようとしていますが、うまくいかないようです - これが正しいパターンであるかどうかわかりませんか?

class A 
{
    void one;
    void two;
    void three;
}

class B
{
    void four;
    void five;
    void six;
    void seven;
}

class C
{
    void eight;
    void nine;
}

これは、私の設計で問題が発生した場所です。具体的な戦略にオブジェクトを渡すにはどうすればよいでしょうか?

class DataParser
{
    Object object;

    void DataParser(Object object)
    {
        this.object = object;

        parsers.put(new ClassA(), new ClassAParser());
        parsers.put(new ClassB(), new ClassBParser());
        parsers.put(new ClassC(), new ClassCParser());
    }

    void writeData()
    {
        ParserInterface parser = parsers.get(this.object);
        /*
         * classAParser.setClassA(object);
         * classBParser.setClassB(object);
         * classCParser.setClassC(object):
        */
        parser.write();
    }
}

.

interface ParserInterface
{
    void write();
    void read();
}

.

class ClassAParser()
{
    ClassA classA;

    void setClassA(ClassA classA)
    {
        this.classA = classA;
    }

    void write()
    {
        PrinterWriter writer = new PrintWriter("ClassA.txt");

        writer.printLn(this.classA.getOne() + "|" + this.classA.getTwo() + "|" + this.classA.getThree());

        writer.close();
    }

    void read()
    {
    }
}

.

class ClassBParser()
{
    ClassB classB;

    void setClassB (ClassB classB )
    {
        this.classB = classB ;
    }

    void write()
    {
        PrinterWriter writer = new PrintWriter("ClassB.txt");

        writer.printLn(this.classB.getFour() + "|" + this.classB.getFive() + "|" + this.classB.getSix() + "|" + this.classB.getSeven());

        writer.close();
    }

    void read()
    {
    }
}

それで、私は単に次のようなことをすることができます:

class Test()
{
    void testClassA()
    {
        ClassA classA = new ClassA();
        classA.setOne("One");
        classA.setTwo("Two");
        classA.setThree("Three");

        DataParser parser = new DataParser(classA);
        parser.writeData();
    }
}

その場合、ClassA.txt は次のようになります: "one|two|three"

4

5 に答える 5

1

パーサーに汎用インターフェースを使用できます。

public interface ParserInterface<T> {
    void setObject(T object);
    void read();
    void write();
}

public class ClassAParser implements ParserInterface<ClassA> { ... }

Pitelk が述べたように、オブジェクトとパーサーのマップが間違っているようです。代わりに、パーサーへのクラスのマップを使用する必要があります。

parsers.add(ClassA.class, new ClassAParser());
// etc.

その上、のコンストラクターですべてのパーサー実装のインスタンスを作成することDataParserは、不要なオーバーヘッドです。if/else ifチェーンを使用して必要なインスタンスのみを作成するObject.getClassinstanceof、コンストラクターで作成するか、マップをクラスの静的メンバーにすることができます。

writeDataその後、次のようになります。

void <T> writeData()
{
    ParserInterface<T> parser = (ParserInterface<T>) parsers.get(this.object.getClass());
    parser.setObject((T) this.object);  // <-- same method for all of supported types
    parser.write();
}

コンパイラは、チェックされていないキャストに関する警告を生成します。しかし、正しく使用された場合、つまりparsers.get(c)、互換性のあるパーサーが返された場合は、無視または抑制できます。

于 2013-09-20T09:40:52.963 に答える
1

クラスにインターフェースを実装させたくない場合は、 Java: If-else instanceof extended classesで説明されているのと同じモードを使用できます。ファクトリ クラスには、書き込むオブジェクトと書き込む場所を渡す必要があります。
もう 1 つの方法は、次のようにテンプレート メソッド パターンを使用することです。

abstract class ParserReaderWriter implements ParserInterface {
  protected abstract String[] getDataToWrite();
  protected abstract PrintWriter createWriter();
  void write() {
    Writer writer = createWriter();

    writer.println(StringUtils.join(getDataToWrite(),"|");
    writer.close();
  }
}

次に、すべてのライターのライターを作成します

class AParserReaderWriter extends ParserReaderWriter {
  ClassA object;
  AParserReaderWriter(ClassA object) {
    this.object = object;
  }
  protected String[] getDataToWrite() {
    return new String[]{this.object.getOne(),...};
  }
  protected PrintWriter createWriter() {
    return new PrintWriter("a.txt");
  }
}
于 2013-09-20T09:41:50.097 に答える
1

戦略インターフェースは、あなたが達成しようとしていることに対して少しやり過ぎかもしれないと思います. インターフェースはおそらくあなたが望むものを手に入れるでしょう:

public interface Writable {
  void writeTo(PrintWriter writer);
}

class A implements Writable {
  String one;
  String two;
  String three;

  public void writeTo(PrintWriter writer) {
    // do the writing here
  }
}

ClassBClassC...を繰り返す

于 2013-09-20T09:23:41.350 に答える
1

ここにロングショットがあります、私はあなたのコードで次を見ました:

  parsers.put(new ClassA(), new ClassAParser());

しかし、私はあなたがこの変数を宣言する場所を見つけることができません(私は間違ったコピー&ペーストだと思います)この場合、クラス A、B、C に equals() と hashCode() の両方を実装する必要があります。理由はこちらをご覧ください

HashMap での equals と hashCode の動作を理解する

http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html

(つまり、これらのメソッドをオーバーライドしない場合、渡したオブジェクトは

       parsers.get(this.object);

マップに配置したオブジェクトの1つとまったく同じインスタンスである必要がありますが、あなたの場合はそうではありません)

于 2013-09-20T09:28:14.133 に答える