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

谢谢,我会检查一下。 –