2015-12-27 57 views
2

我想連接幾個獨立運行但相關的類。連接器設計模式?

可以說我正在寫一個應用程序,您可以在其中滑動繪製圖表。應用程序中有很多類是相關的,應該連接。

例如三個類別是:

組隊,探索 - 負責解釋用戶的手勢

點 - 負責處理圖表上的點

ChartDrawer - 負責繪製在屏幕上的圖表

我想知道是否有任何設計模式,如可以處理這些類的關係和通信的連接器?任何方式,我可以重新設計一個更好的方式,或讓更多的面向對象的頭腦?

這是一種延伸的觀點我ChartDraw類:

public class ChartDraw extends View implements GestureReceiver { 
    int chartYPosition; 
    private int circleColor; 
    private int circleRadius; 
    int height; 
    private float lastPointOnChart; 
    private int lineColor; 
    private int lineWidth; 
    private Paint paint; 
    private float tempPoint; 
    int width; 

    public ChartDraw(Context context) { 
     super(context); 
     init(); 
    } 

    public ChartDraw(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public ChartDraw(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    private void init() { 
     this.lineWidth = 15; 
     this.circleRadius = 20; 
     this.lineColor = Color.parseColor("#1976D2"); 
     this.circleColor = Color.parseColor("#536DFE"); 
     this.lastPointOnChart = 0.0f; 
     this.tempPoint = 0.0f; 
     this.paint = new Paint(); 
     this.height = getHeight(); 
     this.width = getWidth(); 
     this.chartYPosition = this.height/2; 
    } 

    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     this.chartYPosition = canvas.getHeight()/2; 
     this.paint.setStrokeWidth((float) this.lineWidth); 
     this.paint.setColor(this.lineColor); 
     canvas.drawLine(0.0f, (float) this.chartYPosition, this.tempPoint, (float) this.chartYPosition, this.paint); 
     if (this.tempPoint > 20.0f) { 
      this.paint.setColor(this.circleColor); 
      canvas.drawCircle(20.0f, (float) this.chartYPosition, 20.0f, this.paint); 
      drawTriangle(canvas, this.paint, this.tempPoint, this.chartYPosition); 
     } 
    } 

    private void drawTriangle(Canvas canvas, Paint paint, float startX, int startY) { 
     Path path = new Path(); 
     path.moveTo(startX, (float) (startY - 20)); 
     path.lineTo(startX, (float) (startY + 20)); 
     path.lineTo(30.0f + startX, (float) startY); 
     path.lineTo(startX, (float) (startY - 20)); 
     path.close(); 
     canvas.drawPath(path, paint); 
    } 

    public void onMoveHorizontal(float dx) { 
     this.tempPoint = this.lastPointOnChart + dx; 
     invalidate(); 
    } 

    public void onMoveVertical(float dy) { 
    } 

    public void onMovementStop() { 
     this.lastPointOnChart = this.tempPoint; 
    } 
} 

,這是我SwipeManager正在處理用戶的手勢:

public class SwipeManager implements View.OnTouchListener { 
    GestureReceiver receiver; 
    private int activePointer; 

    private float initX, 
      initY; 
    private long startTime, 
      stopTime; 

    private boolean resolving = false; 
    private boolean resolved = false; 

    private Direction direction; 

    @Override 
    public boolean onTouch(View view, MotionEvent motionEvent) { 
     if (receiver == null) throw new AssertionError("You must register a receiver"); 
     switch (motionEvent.getActionMasked()) { 
      case ACTION_DOWN: 
       activePointer = motionEvent.getPointerId(0); 

       initX = motionEvent.getX(activePointer); 
       initY = motionEvent.getY(activePointer); 

       startTime = new Date().getTime(); 
       break; 

      case ACTION_MOVE: 
       if (!resolving && !resolved) { 
        resolving = true; 
        float x = motionEvent.getX(activePointer); 
        float y = motionEvent.getY(activePointer); 
        direction = resolveDirection(x, y); 
        if (direction != Direction.STILL) { 
         resolved = true; 
         resolving = false; 
        } else { 
         resolving = false; 
         resolved = false; 
        } 
        break; 
       } 

       if (resolved) { 
        if (direction == Direction.HORIZONTAL) 
         receiver.onMoveHorizontal(motionEvent.getX(activePointer) - initX); 
        else receiver.onMoveVertical(motionEvent.getX(activePointer) - initY); 
       } 
       break; 

      case ACTION_UP: 
       resolved = false; 
       receiver.onMovementStop(); 
       break; 
     } 
     return true; 
    } 

    private Direction resolveDirection(float x, float y) { 
     float dx = x - initX; 
     float dy = y - initY; 
     float absDx = Math.abs(dx); 
     float absDy = Math.abs(dy); 
     if (absDx > absDy + 10) { 
      return Direction.HORIZONTAL; 
     } else if (absDy > absDx + 10) { 
      return Direction.VERTICAL; 
     } 
     return Direction.STILL; 
    } 

    public void setReceiver(GestureReceiver receiver) { 
     this.receiver = receiver; 
    } 

    private enum Direction {HORIZONTAL, VERTICAL, STILL;} 
} 

,我並沒有啓動點類,因爲我對架構並不確定。

我想讓這個連接器爲這些類註冊所有的監聽器,然後等待一個改變並通知相應的改變類,比如新增的點或者刷卡開始和結束或者應用中的其他事件。

+0

不要道歉,只是編輯問題,這樣可以回答 – AdamSkywalker

+0

@AdamSkywalker我該如何編輯?我想我很清楚... –

+0

從這個連接器寫一些代碼和您的期望 – AdamSkywalker

回答

2

Chain of Responsibility可能是你在找什麼。

這是一種模式,可以在可以處理'命令對象'的'鏈'中綁定一系列'處理對象'。

我可以看到你製作封裝觸摸事件的命令對象,然後通過幾個處理器傳遞,最後通過處理該特定「命令對象」的輸入檢測/輸出生成的「處理對象」得到'處理'。

我不知道這是否是 - 理想的,但它可能是有效的。

其他相關模式尋找到可能是:

https://en.wikipedia.org/wiki/Command_pattern

https://en.wikipedia.org/wiki/Observer_pattern

https://en.wikipedia.org/wiki/Bridge_pattern

+0

感謝您的答覆。我會檢查這些模式 –

1

真的是你要找的東西在這裏是一個MVC風格的建築。你的應用程序應該(廣義上)被分成3個不同的領域:

  • 的模式,這是完全從您的演示文稿或通信擔憂離婚。它提供了一個用於交互的API,並且可以通過一個簡單的框架(如JUnit)完全獨立地進行測試。

  • 該視圖負責顯示模型。這可能是一個模型可以以不同的方式顯示 - 在這種情況下,你可以得到一個模型和幾個不同的視圖。

  • 控制器,負責響應用戶(或其他)輸入對模型進行更改。

重要的是,這三個組件集是鬆耦合和責任明確分開。所有這三個應該通過定義良好的接口進行交流(可能使用Observer,Command和ChainOfResponsibility模式)。特別是,Model類應該沒有任何View或Controller類的直接知識。

所以,你可能有一些模型/視圖類這樣的...

public interface ChartListener { 
    void notifyUpdate(); 
} 

public interface Chart { 
    void newPoint(Point p); 

    Collection<Point> thePoints(); 

    void addListener(ChartListener listener); 
} 

public class ChartModel implements Chart { 
    private final Collection<Point> points; 
    private final Collection<ChartListener> listeners; 

    public Collection<Point> thePoints() { 
     return Collections.unmodifiableCollection(points); 
    } 

    public void newPoint(Point p) { 
     thePoints.add(p); 
     listeners.stream().forEach(ChartListener::notifyUpdate); 
    } 

    public void addListener(ChartListener cl) { 
     listeners.append(cl); 
    } 
} 

public PieChartViewer implements ChartListener { 
    // All you colour management or appearance-related concerns is in this class. 
    private final Chart chart; 

    public PieChartView(Chart chart) { 
     this.chart = chart; 
     // set up all the visuals... 
    } 

    public void notifyUpdate() { 
     for (final Point p:chart.thePoints()) { 
      // draw a point somehow, lines, dots, etc, 
     } 
    } 
} 

這時,你可能有你的視圖類的多種不同的實現方式,利用ChartListener接口。

您的Swipe類看起來像一個Controller類,它需要一個ChartModel實現,然後修改它以響應來自用戶的某些輸入。

+0

謝謝,我會檢查一下。 –