访问/修改深层嵌套对象的正确方法是什么?
请看下面的例子。
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
的类。 PenTool
,LineTool
,CircleTool
是它的子类。
Shape
是用于绘制的类。 Pen
,Line
,Circle
是它的子类。
现在来自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)
但似乎我正在以这种方式打破封装。
有没有更好的方法来处理这种情况?
答案 0 :(得分:0)
使用共享对象的最后一个示例并没有真正打破封装,并且接近我建议通过结合依赖性反转和关注点分离的概念来实现它。
我唯一要问的是为什么鼠标跟踪器会关心当前使用的工具。根据其名称,它应该只涉及跟踪鼠标和确定位置数据;可能包含一些方便的方法来确定状态,如IsDragging
属性。然后控制器类(在这种情况下是绘图板)应该获取该数据(和/或响应跟踪器发布的鼠标状态更改事件)并结合工具生成的结果使用它来更新绘图空间
所有这些说明,原始问题的答案是将这种深度访问视为编码气味,并确保您不能使用SOLID原则和常见模式来改变设计。如果您的设计确实需要深入访问,请根据具体情况确定消费者是否需要深入访问完整对象或单个属性。如果是前者,则公开子对象。如果是后者,请创建一个可以获得所需内容的包装器属性。在每个级别做出决定,然后访问每个级别最深的可用属性。基本上你只需要在不希望暴露所有东西之间找到平衡点,而不想在每个对象上总是有十亿个属性来访问更深层的对象。