2013-03-25 65 views
4

對於下面的模型,你願意繼承或組成:畫布形狀模型的繼承vs組合?

  • 我要畫上一個canvas每個代表一個數據對象
  • 認爲它像一個狀態機圖對象:Ellipses代表StatesLines代表它們之間的connections/transitions。對象表示本身永遠不會改變,即State將始終顯示ellipse。但是,一個ellipse被吸入的方式應有所不同,例如,用於選擇應該具有不同的顏色,同時拖動它應該可能具有alpha通道等

從設計角度來看,一個ellipse不是stateline不是transition。無論如何,將兩個對象組合起來以便能夠在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 

雖然從設計的角度來看一個rectangle不是Statestate不是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將是我的對象的包裝。

矩形和線條應該延伸狀態和過渡還是包含它?

或者,也許還有第三個設計選項,我沒有看到。期待您的想法。

+1

我使用Eclipse建模框架(EMF)做了類似的工作,也就是使用模型驅動技術。您將爲數據創建一個領域模型,一個用於圖形表示,另一個用於連接兩個元素。這需要一定的紀律,但最終還是可以得到回報的。 – 2013-03-25 21:37:08

回答

2

所以,這是我的想法,但對於大多數設計問題,很少有一個「正確的」答案。

就像你說的,一個國家不是一個矩形,並且一個轉換不是一條線。我們可以繪製一條線和/或一個矩形,並且可能會有類似的處理它們的優點。所以我可以將這些語句翻譯成一個簡單的設計:

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

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

現在,State和Transition可以用這些Drawable表示。你有沒有聽說過單一責任原則?這基本上就是它聽起來像,一個對象應該負責做一件「事情」。矩形和線條知道如何繪製自己。在你的系統中,狀態和轉換可能有其他工作要做。

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的優勢可能會丟失,但這個想法是,我們分開其他系統邏輯渲染。我們分離功能越多,變化時間到來時系統就越脆弱。

+0

這種SRP方法對我來說很有意義! – membersound 2013-03-26 23:02:16

0

首先我相信你是不正確的建模,一個橢圓不代表一個國家,但一個國家代表一個橢圓。正如你所說的那樣,一個國家不是一個橢圓。所以你應該有構圖,我會選擇狀態對象表示它的形狀。

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); 
} 

而且它是國家有責任知道他們的轉換(或過渡責任瞭解它們所連接的國家)必須與形狀抽象出來的東西,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()); 
    } 
}