5

次のモデルでは、継承または構成のどちらを使用しますか。

  • canvasそれぞれがデータオブジェクトを表すオブジェクトを描画したい
  • ステートマシン図のように考えてください。Ellipses表現しStates、それらの間をLines表現connections/transitionsします。オブジェクト表現自体は決して変更されません。つまり、aStateは常に。で示されますellipse。ただし、ellipse描画方法は異なる必要があります。たとえば、選択の場合は色を変え、ドラッグする場合はアルファチャネルなどを使用する必要があります。

設計の観点から、anellipseはではなく、statealineはではありませんtransition。とにかく、両方のオブジェクトを組み合わせて、それらをaに収集し、すべてのオブジェクトList<Shape>で実行できるようにするのが適切です。shape.draw()

現在、2つの設計モデルが可能ですが、2つのクラスは常に同じであると考えています。

interface Shape {
    void draw();
}
abstract class Figure implements Shape {
    //basic vars like start and end coordinates
    int x0, y0, x1, y1;
}

継承:

abstract class State extends Figure {
    String name;
}
class Rectangle extends State {
    @Override void draw();
}

class Line extends Figure;
class Transition extends Line

設計の観点からは、aはではrectangleなく、Stateastateはではありませんがfigure、描画コンテキストに関しては、これは実行可能である可能性があります。shapes、描画などの処理に必要なもののほとんどを継承できたからです。

または構成:

abstract class State {
    String name;
}

class Rectangle extends Figure {
    private State state;
    @Override void draw();
}
class Line extends Figure {
    private Transition transition;
    @Override void draw();
}

したがって、Rectangle+Lineは私のオブジェクトのラッパーになります。

長方形と線はむしろ状態と遷移を拡張するべきですか、それともそれを含むべきですか?

または、私が見なかった3番目のデザインオプションもあるかもしれません。あなたのアイデアを楽しみにしています。

4

2 に答える 2

2

それで、これが私の考えですが、ほとんどの設計上の質問では、「正しい」答えが1つあることはめったにありません。

あなたが言ったように、状態は長方形ではなく、遷移は線ではありません。線や長方形を描くことができ、それらを同様に扱うことにはいくつかの利点があるかもしれません。したがって、これらのステートメントを単純な設計に変換できます。

public interface Drawable 
{
  public void draw();
  public Position getPos();
}

public class Rectangle implements Drawable ...
public class Line implements Drawable ...

これで、StateとTransitionをこれらのDrawableで表すことができます。単一責任原則について聞いたことがありますか?それは基本的にそれがどのように聞こえるかとまったく同じです、オブジェクトは1つの「こと」をする責任があるべきです。長方形と線は、自分自身を描く方法を知っています。状態と遷移には、おそらくシステムで行うべき他の仕事があります。

public interface Figure 
{
   public Drawable getDrawable();
}

public class State implements Figure
{
   private Rectangle rect;

   public Drawable getDrawable() { return rect; }

   //... State's real "work" below
}

public class Transition implements Figure
{
   private Line line;
   // you get the idea
}

小規模/単純なシステムでは、SRPの利点が失われる可能性がありますが、レンダリングを他のシステムロジックから分離しているという考え方です。機能を分離すればするほど、変更の時期が来たときにシステムが脆弱になることは少なくなります。

于 2013-03-25T21:40:06.217 に答える
0

まず、あなたはそれを間違ってモデル化していると思います。楕円は状態を表していませんが、状態は楕円で表されています。そして、あなたがそれを非常によく言うように、州は楕円ではありません。したがって、コンポジションが必要です。Stateオブジェクトを選択し、それを表すShapeを作成します。

abstract class State
{
    private Shape shape;
}

形状を選択可能にし、それを状態から抽象化しておくには、選択可能な形状のインターフェイスが必要です。

interface SelectableShape
{
    void setSelected();
    void setUnselected();
}

上記に加えて、たとえば長方形をトランジションを介して別の長方形に接続する場合は、ConnectableShapeやShapeConnectionなどの追加のインターフェイスを宣言する必要があります。

interface ConnectableShape extends 
{
}

interface ShapeConnection
{
    void connect(ConnectableShape sh1, ConnectableShape sh2);
}

また、遷移を知ることは州の責任です(または、接続する状態を知ることは遷移の責任です)。Shape、ConnectableShape、ShapeConnectionで抽象化する必要があるのは、そのすべての表現です。したがって、次のようなことをするのは悪い設計ではありません。

abstract class State
{
    private ConnectableShape shape;
    public ConnectableShape getShape() {
        return shape;
    }
}

abstract class Transition
{
    private ShapeConnection conn;
    public void connect(State s1, State s2) {
        conn.connect(s1.getShape(),s2.getShape());
    }
}
于 2013-03-25T21:34:00.993 に答える