修改深层嵌套的依赖项

时间:2015-04-16 08:44:51

标签: design-patterns dependency-injection dependencies

访问/修改深层嵌套对象的正确方法是什么?

请看下面的例子。

public class DrawBoard
{
    MouseTracker mouseTracker_;
    DrawTool* drawTool_;

    void init()
    {
        mouseTracker_ = new MouseTracker(area);
        mouseTracker_.setTool(new PenTool());
    }

    void OnMouseEvent(MouseEvent e)
    {
        mouseTracker_->handleMouseEvent(e);
    }

    //UI Button setting the tool
    void OnPenButtonClick()
    {
        mouseTracker_.SetTool(new PenTool());
    }

    void OnLineButtonClick()
    {
        mouseTracker_.SetTool(new LineTool());
    }

    void OnCircleButtonClick()
    {
        mouseTracker_.SetTool(new CircleTool());
    }

    //UI slide bar changing the color
    void OnColorSlideBarChange(int color)
    {
        //What should I do here?
        //Chained getters : mouseTracker.getDrawTool().setColor(color);
        //Delegate Method: mouseTracker.setColor(color);
        //Shared Object: Store the current tool in "drawTool_" -    drawTool_ = new PenTool(); 
        //                                                          mouseTracker_.SetTool(drawTool_);
        //and just call drawTool_.setColor(color) on color change
    }
}

public class MouseTracker;
{
    DrawTool* tool_;

    void handleMouseEvent(MouseEvent e)
    {
        Shape s = tool->process(e)
        s.Draw();
    }

    void SetTool(DrawTool tool)
    {
        tool_ = tool;
    }
}

public class DrawTool
{
    int color_;

    Shape* process(MouseEvent e)
    {
        /** process e **/
        Shape s = new Pen\Line\Circle(color_);
        return s;
    }

    void SetColor(int color)
    {
        color_ = color;
    }

} PenTool, LineTool, CircleTool;

public class Shape
{
    void Draw() {  Implementation };

} Pen, Line, Circle;

DrawBoard是一个UI类。

MouseTracker是一个用于处理事件并采取相应行动的类。

DrawTool是用于创建Shapes的类。 PenToolLineToolCircleTool是它的子类。

Shape是用于绘制的类。 PenLineCircle是它的子类。

现在来自DrawBoard,我正在尝试根据UI事件(在本例中为OnColorSlideBarChange)更改drawTool的颜色。我只能看到3种方法。

链式吸气剂

mouseTracker.getDrawTool().setColor(color); 但上面的例子是一个简化的案例。如果它们之间存在更多依赖关系。它可以快速成长为

mouseTracker.getA().getB().getC().getDrawTool().setColor(color);我必须为每个班级编写一个getter方法。

委托方法

mouseTracker.setColor(color);

与上面类似,除了我在一个委托方法中隐藏细节。

共享对象

将当前工具存储在DrawBoard类中的“drawTool_”中,并在每次换刀时更新它

drawTool_ = new PenTool(); 
mouseTracker_.SetTool(drawTool_);

更改颜色只是

drawTool_.setColor(color)

但似乎我正在以这种方式打破封装。

有没有更好的方法来处理这种情况?

1 个答案:

答案 0 :(得分:0)

使用共享对象的最后一个示例并没有真正打破封装,并且接近我建议通过结合依赖性反转和关注点分离的概念来实现它。

我唯一要问的是为什么鼠标跟踪器会关心当前使用的工具。根据其名称,它应该只涉及跟踪鼠标和确定位置数据;可能包含一些方便的方法来确定状态,如IsDragging属性。然后控制器类(在这种情况下是绘图板)应该获取该数据(和/或响应跟踪器发布的鼠标状态更改事件)并结合工具生成的结果使用它来更新绘图空间

所有这些说明,原始问题的答案是将这种深度访问视为编码气味,并确保您不能使用SOLID原则和常见模式来改变设计。如果您的设计确实需要深入访问,请根据具体情况确定消费者是否需要深入访问完整对象或单个属性。如果是前者,则公开子对象。如果是后者,请创建一个可以获得所需内容的包装器属性。在每个级别做出决定,然后访问每个级别最深的可用属性。基本上你只需要在不希望暴露所有东西之间找到平衡点,而不想在每个对象上总是有十亿个属性来访问更深层的对象。