2012-02-05 10 views
2

基本的なOOPの概念の理解に問題があります。私はそれを例で説明しようとします。いろいろな形の図形を描くアプリケーションがあるとしましょう。OOPで図階層を実装する方法

私はFigureクラスを作成し、フィールドShapeを追加します(これは列挙の一種であり、Shape.CircleまたはShape.Squareでもかまいません)。

public class Figure { 
    public Shape shape; 

    public void draw() { 
     if(shape == Shape.Square) 
      // draw a square 
     else if(shape == Shape.Circle) 
      // draw a circle 
    } 
} 

アプリケーションにさらにシェイプを追加する必要がある場合は、if()メソッドを追加する必要があります。私はそれが悪いと思う。

図形クラスを抽象的な(またはそれをインタフェースにして)作成し、このクラスから具体的な図形を継承し、draw()メソッドをオーバーライドすることができます。

public abstract Figure { void draw(); } 

public class Circle extends Figure { 
    @Override public void draw() { 
     // draw a circle 
    } 
} 

// same for Square 

私は新しい形を追加するだけで新しいクラスを追加します。

次のように、私は私の人物の色を黒または白にしたいと決めました。黒い正方形と白い四角形を別々に描画する必要があります。問題は同じように見えます。私は、Figureクラスにカラーフィールドを追加し、それぞれの描画メソッドでifを処理したり、BlackCircle、BlackSquare、WhiteCircle、WhiteSquareのようなクラスを作成することができます。

後でFigureの別のプロパティを追加することにした場合(SizeはSmall、Medium、Large)、BigBlackCircle、SmallWhiteSquareなどの2 * 2 * 3クラスを作成する必要があります。また、実行時にFigureの色や形を変更することはできません。私はそれが正しい方法ではないと思う。

問題を理解しようとすると、私はまだすべての人物のために単一のクラスを持つことができることがわかりました。次に、色、形状、サイズをフィールドとして保存し、描画を担当する種類のDisplayManagerクラスを追加します。私は異なる描画アルゴリズムのためにDisplayManagerの異なる実装を持つことができます。

public class Figure { 
    public Shape shape; 
    public Color color; 
    public Size size; 
    public DisplayManager display; 

    public void draw() { 
     display.draw(this); 
    } 
} 

public class DisplayManager { 
    public void draw(Figure figure) { 
     // drawing based on figure's shape, color and size 
    } 
} 

しかし、この方法では、手順1の問題に戻ります。draw()メソッドで多くのifを処理する必要があります。誰でもここで正しい方法を説明できますか?アプリケーションの柔軟性を節約するために、クラスをどのように設計する必要がありますか?

答えて

3

DisplayManager.draw(Figure)を宣言する代わりに、Figure.draw(DisplayManager)と宣言します。それはFigureから使用できるように、DisplayManagerいくつかのメソッドの実装[drawPoint()、drawLine()、...]

そしてFigureの各拡張のために、所与DisplayManager

の特定のインスタンスを使用して独自 draw(DisplayManager)を実装
+0

ありがとうございました。私はGoFのデザインパターンでほぼ同じソリューションを見つけました。 – Soteric

2

amitと書かれていて、if文やクラスの他のプロパティを使って、Squareクラスのdraw()メソッドで黒または白の四角形を描画するさまざまな方法を扱うことができます。

例えば、colorプロパティと、Squareを描画する様々な方法を列挙する別の列挙型プロパティを持ち、draw()メソッドで処理することができます。一例として、

、サイズのものが概念を表示するにはスローで:

public abstract class Figure { 
    public enum Size { 
     SMALL(10), MEDIUM(20), LARGE(30); 

     private int actualSize; 

     private Size(int actualSize) { 
      this.actualSize = actualSize; 
     } 

     public int getActualSize() { 
      return actualSize; 
     } 
    } 

    public int x,y; 

    public Size size = Size.MEDIUM; 

    public Color color = Color.BLACK; 

    public abstract void draw(DisplayManager displayManager); 
} 

public class Square extends Figure { 
    public enum Corners { 
     SHARP, ROUNDED 
    } 

    public Corners corners = Corners.SHARP; 

    @Override 
    public void draw(DisplayManager displayManager) { 
     int s = size.getActualSize(); 
     displayManager.setColor(color); 

     switch (corners) { 
     case SHARP: 
      displayManager.drawBox(x-s, y-s, x+s, y+s); 
      break; 
     case ROUNDED: 
      displayManager.drawRoundedBox(x-s, y-s, x+s, y+s); 
      break; 
     } 
    } 
} 

(プロパティのゲッター/セッター該当する場合に私的使用、スペースを節約するために公開され、およびプロパティを設定する必要があります、もちろん:))

ここでは、列挙型は実際には描画に使用できるデータを保持していますが、もう1つは弁別子として機能しています。

関連する問題