7

質問

複数のオブジェクトが関係する機能を実行する際に、 「教えて、尋ねるな」の原則を守るにはどうすればよいですか。

例 - レポートの生成

次のオブジェクトがあります(説明のみを目的としています):

車、馬、うさぎ

これらのオブジェクト間に関係はありませんが、これらのオブジェクトに基づいてレポートを生成したいと考えています:

createHtmlReport(Car car, Horse horse, Rabbit rabbit){
    Report report = new Report()

    report.setSomeField(car.getSerialNumber())
    report.setAnotherField(horse.getNumberOfLegs())
    // ...etc       
}

この方法の問題点は、各オブジェクトからデータを「プル」する必要があることです。これは、「教えて、尋ねるな」という規則に違反しています。各オブジェクトの内部を非表示にして、レポートを生成してもらいたいと思います。

car.createHtmlReport()   
horse.createHtmlReport()
rabbit.createHtmlReport()

...しかし、3 つの部分的なレポートが表示されます。さらに、必要なすべてのレポート (HTML、JMS、XML、JSON ....) を生成する方法を、Rabbit が知る必要はないと思います。

最後に、レポートの生成中に、複数の項目をオンにしたい場合があります。

if (car.getWheels() == 4 || horse.getLegs() == 4)
    // do something
4

4 に答える 4

8

レポートは、自己を作成する機能を維持する必要があります。

この場合、各IReportableオブジェクトは Implement する必要がありますvoid UpdateReport(Report aReport)

Report.CreateReport(List<Reportable> aList)呼び出されると、 List と各オブジェクトを独自のUpdateReport呼び出しの実装で反復処理します。

aReport.AddCar(serialNumber)
aReport.AddHorse(horseName)

の最後にCreateReport、レポート オブジェクトは独自の結果を生成する必要があります。

于 2012-03-09T15:53:24.500 に答える
6

「Tell don't ask」ルールの目的は、特定のオブジェクトにあるはずの責任が、そのオブジェクトの外部で実装されてしまう状況 (悪いこと) を特定するのに役立つことです。
あなたの場合、どのような責任が見られますか? 私が見ているのは次のとおりです

。1)レポートのフォーマット方法(xml、ascii、htmlなど)
を知っている2)どのレポートで何が起こるかを知っている

最初のものは明らかにドメイン オブジェクト (車、馬など) に属していません。2)はどこに行くべきですか?ドメインオブジェクトを提案することもできますが、システムに複数の異なるレポートがある場合、見た目も悪臭もするさまざまなレポートの詳細に関する知識でオブジェクトに負担をかけることになります。単一責任の原則に違反することは言うまでもありません。うさぎであることは 1 つのことですが、うさぎの情報のどの部分をレポート X とレポート Y に記載する必要があるかを知ることはまったく別のことです。したがって、特定の種類のレポートに表示されるデータ コンテンツをカプセル化するクラスを設計します (必要な計算を実行する可能性もあります)。Rabbit、Horse、Car のデータ メンバーを読み取ることについては心配しません。このクラスが実装する責任は、「レポートの特定のタイプのデータを収集する」ことです。

于 2012-03-10T03:34:39.020 に答える
3

それがまさに訪問者パターンの目的です。

于 2012-03-10T03:51:16.037 に答える
1

このパターンの名前は正確にはわかりません(Visitor、Builder、...):

public interface HorseView {
    void showNumberOfLegs(int number);
}

public interface CarView {
    void showNumberOfWheels(int number);
    void showSerialNumber(String serialNumber);
}

public class Horse {

    void show(HorseView view) {
        view.showNumberOfLegs(this.numberOfLegs);
    }

}

public class Car {

    void show(CarView view) {
        view.showNumberOfWheels(this.numberOfWheels);
        view.showSerialNumber(this.serialNumber);
    }

}

public class HtmlReport implements HorseView, CarView {

    public void showNumberOfLegs(int number) {
        ...
    }

    public void showNumberOfWheels(int number) {
        ...
    }

    public void showSerialNumber(String serialNumber) {
        ...
    }

}

public XmlModel implements HorseView, CarView {
    ...
}

public JsonModel implements HorseView, CarView {
    ...
}

このようにして、「聞かないでください」の原則に違反することなく、同じドメインオブジェクトの複数の表現を持つことができます。

于 2013-01-27T19:51:51.413 に答える