作为 OO 的新手,我经常觉得我理解了一个概念,直到我尝试从一个简化的示例转移到给我的实际需求。对于理解如何思考这个特定问题的任何帮助,我将不胜感激。
我有一个 GUI,它有一个面板,它定义了一个容器和其中的项目。目前,有三种类型的容器。容器具有一些属性(如大小),可以包含一到三种不同类型的项目(两种是可选的)。一旦输入了足够的信息,我就会使用这些信息来制作图表。
我实现了一个观察者模式。当用户输入信息时,它会更新一个 observable,它会通知图形它已更改。
到目前为止我很高兴。现在皱纹。我的容器有一个大小,但有时它是明确输入的,有时它是由容器所容纳的东西决定的。这取决于容器的类型。如果没有明确输入,如何确定大小取决于可选项目之一是否在容器中。我不确定需求编写者只是讨厌我还是我缺乏足够的 OO 经验,但是这些皱纹让我很不舒服。现在,我的 observable 只有变量来保存所有分类信息,我使用一堆 switch 语句来处理特殊情况。
我在想我可以使用构建器模式。导演将产生被绘制的数据。我将为每种类型的容器都有一个具体的构建器,并且我将使用容器属性和其中的项目来实例化该类。我将使用抽象构建器类的方法将图形所需的值返回给主管,例如 getContainerSize() 并将它们组合起来以生成实际的数据点。此外,如果用户还没有输入足够的数据来完成图表,director 可能会返回 null。
我是否正在接近可用的 OO 设计?我不确定我是否只是将特殊外壳埋得更深一些。
另一种皱纹。其中一种物品类型放在所有三个容器中。现在,我的 observable 分别跟踪容器和项目,创建图表的方法决定了要求的内容(随着用户使用这些值,图表会发生很大变化)。如果我有多个构建器模式,那将如何工作?
也许我错过了一步?observable 更新当前容器的构建器,然后让图知道它应该调用 director 来获取它的坐标?那么哪个还需要询问当前容器是什么?
欢迎所有评论帮助我了解 OO 设计,尤其是这个问题。实际需求有更多的特殊情况,但都是在这个基本主题上的变化。
感谢您的回复。我认为我将两个问题混为一谈而感到内疚。这里尝试提供一个专注于 Builder 模式的最小代码示例。注意 IE8 我看不到任何身份,FireFox 8,我很抱歉任何阅读 IE8 代码的人。
interface MyContainerBuilder
{
void setContents( MyContents contents );
Double myVolume();
Double myDensity();
}
class SmallContainerBuilder implements MyContainerBuilder
{
Double volume = null;
Double density = null;
MyContents contents = null;
public void setVolume()
{
if (contents != null)
{
volume = contents.myDensity() / 3.0;
}
}
public void setContents( MyContents contents )
{
this.contents = contents;
}
public Double myVolume()
{
if (volume == null)
setVolume();
return volume;
}
public Double myDensity()
{
return contents.myDensity();
}
}
class BigContainerBuilder implements MyContainerBuilder
{
Double volume = null;
Double density = null;
MyContents contents = null;
public void setVolume( Double volume )
{
this.volume = volume;
}
public void setContents( MyContents contents )
{
this.contents = contents;
}
public Double myVolume()
{
return volume;
}
public Double myDensity()
{
return contents.myDensity();
}
}
class ContainerDirector
{
Double myResult( MyContainerBuilder container )
{
return container.myVolume() * container.myDensity();
}
}
class MyContents
{
Double density;
MyContents( Double density )
{
this.density = density;
}
public Double myDensity()
{
return density;
}
}
class Test
{
public static void main(String[] args)
{
SmallContainerBuilder smallContainer = new SmallContainerBuilder();
BigContainerBuilder bigContainer = new BigContainerBuilder();
ContainerDirector director = new ContainerDirector();
//
// Assume this comes from the GUI, where an ActionListener knows which Builder
// to use based on the user's action. I'd be having my observable store this.
Double density = 15.0;
MyContents contents = new MyContents( density );
smallContainer.setContents( contents );
//
// Then I would need to tell my observer to do this.
Double results = director.myResult( smallContainer );
System.out.println( "Use this result: " + results );
}
}
我有两种类型的容器,它们使用不同的方法来计算体积。因此,假设我有单选按钮来选择容器类型,并且在每个单选按钮下都有一个可以进入所选容器的项目组合框。组合框上的 ActionListener 会将项目放在正确的容器中并将其保存到我的 observable 中(实际上还有很多其他的东西被设置),它告诉我的观察者使用 director 来获取适当的值,然后观察者更新GUI的一些视图组件。