修改深度嵌套的依赖

Modifiy deeply nested dependencies

accessing/modifying深度嵌套对象的正确方法是什么?

看下面的例子。

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 class.

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

DrawTool 是用来创建 Shapes 的 class。 PenToolLineToolCircleTool 是它的子class。

Shape就是用来画的class。 PenLineCircle 是它的子class。

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

连锁getters

mouseTracker.getDrawTool().setColor(color); 但上面的例子是一个简化的案例。如果 between.It 中有更多的依赖项,可能会迅速增长到

mouseTracker.getA().getB().getC().getDrawTool().setColor(color); 而且我必须为每个 class.

编写一个 getter 方法

委托方法

mouseTracker.setColor(color);

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

共享对象

DrawBoard class 内将当前刀具存储在 "drawTool_" 中,并在每次刀具更换时更新它

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

改变颜色就是

drawTool_.setColor(color)

但我这样做似乎破坏了封装。

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

你最后一个使用共享对象的例子并没有真正破坏封装,而是接近于我推荐的结合依赖倒置和关注点分离概念的方式。

我唯一想问的是为什么鼠标跟踪器关心当前使用的是什么工具。根据它的名字,它应该只关心跟踪鼠标和确定位置数据;可能包装一些方便的方法来确定状态,比如 IsDragging 属性。控制器 class(在本例中为绘图板)然后应获取该数据(and/or 响应您的跟踪器发布的鼠标状态更改事件)并结合工具生成的结果使用它, 更新您的绘图 space.

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