Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这是否是Java中构建器模式的有效使用(甚至是良好的OO设计)?_Java_Design Patterns - Fatal编程技术网

这是否是Java中构建器模式的有效使用(甚至是良好的OO设计)?

这是否是Java中构建器模式的有效使用(甚至是良好的OO设计)?,java,design-patterns,Java,Design Patterns,作为一个对OO相当陌生的人,我经常觉得我理解了一个概念,直到我试图从一个简化的例子转移到我所得到的实际需求。我非常感谢您能帮助我理解如何思考这个问题 我有一个GUI,它有一个面板,用于定义容器和其中的项目。现在,有三种类型的容器。容器具有一些属性(如大小),可以包含一到三种不同类型的项目(两种是可选的)。一旦输入了足够的信息,我就用这些信息制作一个图表 我实现了一个观察者模式。当用户输入信息时,它会更新一个可观察对象,通知图形它已更改 到目前为止我很高兴。现在是皱纹。我的容器有一个大小,但有时它

作为一个对OO相当陌生的人,我经常觉得我理解了一个概念,直到我试图从一个简化的例子转移到我所得到的实际需求。我非常感谢您能帮助我理解如何思考这个问题

我有一个GUI,它有一个面板,用于定义容器和其中的项目。现在,有三种类型的容器。容器具有一些属性(如大小),可以包含一到三种不同类型的项目(两种是可选的)。一旦输入了足够的信息,我就用这些信息制作一个图表

我实现了一个观察者模式。当用户输入信息时,它会更新一个可观察对象,通知图形它已更改

到目前为止我很高兴。现在是皱纹。我的容器有一个大小,但有时它是显式输入的,有时它是由容器所容纳的内容决定的。这取决于容器的类型。如果未明确输入,大小的确定方式取决于容器中是否有一个可选项。我不确定需求编写者是否讨厌我,或者我缺乏足够的OO经验,但这些皱纹让我感到不适。现在,我的observable只有变量来保存所有分类信息,我使用了一组switch语句来处理特殊情况

我想我可以使用builder模式。主任将生成绘制的数据。对于每种类型的容器,我都会有一个具体的生成器,我会用容器属性和其中的项实例化这个类。我将使用抽象生成器类的方法将图形所需的值返回给控制器,例如getContainerSize(),并将这些值组合起来生成实际的数据点。此外,如果用户尚未输入足够的数据来完成图形,则控制器可能会返回null

我正在接近一个可用的OO设计吗?我不确定我没有把特殊的外壳埋得更深一点

另一条皱纹。三个容器中都有一个项目类型。现在,我的observable分别跟踪容器和项目,并且创建图形的方法决定要请求什么(当用户处理这些值时,图形会发生很大变化)。如果我有多个构建器模式,这是如何工作的

也许我错过了一步?observable更新当前容器的构建器,然后让图形知道它应该调用控制器来获取其坐标?然后还需要询问当前容器是什么

欢迎所有有助于我了解OO设计或这个问题的评论。实际需求有更多的特殊情况,但都是这一基本主题的变体

谢谢你的回复。我认为我把两个问题混在一起是有罪的。这里尝试提供一个关于构建器模式的最小代码示例。注意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的一些视图组件

我的容器有一个大小,但有时它是显式输入的,有时它是由容器所容纳的内容决定的。这取决于容器的类型。[…]如果未显式输入,则取决于容器中是否有一个可选项

听起来一个抽象容器可能有不同的子类,每个子类以不同的方式实现
getContainerSize()
。一个用于显式输入,一个用于带有可选项的情况,另一个用于不带可选项的情况

。。。我用一堆switch语句来处理特殊情况

听起来不太好。如适用

我想我可以使用生成器模式

我假设您需要根据一组输入变量确定对象的具体类型(或
null
)。如果模式知道复杂对象的类型,那么它提供了一种构建复杂对象的方法,但实际问题是确定哪种类型。所以你需要在某个地方使用条件代码。那个地方可以是一个建筑商,但也可以是一个简单的工厂

现在,我的observable分别跟踪容器和项目[…]observable更新当前容器的构建器[…]如果我有多个构建器模式,这是如何工作的

并没有真正理解可观察到的是什么,以及在哪种情况下哪些更改触发了什么,但可观察到的对构建器(或多个)的更新听起来很奇怪。不过这更像是一种直觉:)

我正在接近一个可用的OO设计吗

如果有效的话,是的。但是我实际上不能告诉你你是否创造了一个好的或者有用的设计,因为我仍然不知道你的问题或者你的设计的细节——在阅读了你的文章好几次之后

现在不要在你的问题上再添加一页信息,试着将你的问题分解成更小的部分,并使用代码片段/图像/图形或任何类型的可视化来帮助人们理解你的问题以及这些部分之间的所有联系。仅仅是大量的文本是相当可怕的,像这样一个巨大的OO设计作为一个整体来说太大了,太本地化了


您的方法看起来不错,但它需要非常复杂的对象来证明这种使用

您可以通过observer在GUI中创建MyContents实例。然后将该对象包装在MyCo中
MyContents content1 = new MyContents( 5 );
MyContents content2 = new MyContents( 6 );
smallContainer.setContents( content1 );
smallContainer.setContents( content2 ); // overwriting old state
Double results1 = director.myResult( smallContainer ); // wrong result
Double results2 = director.myResult( smallContainer );
interface VolumeStrategy {
     Double calculateVolume(Double density);
}
class SmallVolumeStrategy implements VolumeStrategy {
    public Double calculateVolume(Double density) {
        return density / 3.0;
    }
}
class BigVolumeStrategy implements VolumeStrategy {
    public Double calculateVolume(Double density) {
        return density;
    }
}

class ContainerDirector {
    Double myResult( MyContents container ) {
        Double density = container.myDensity();
        VolumeStrategy strategy = container.myStrategy();
        return density * strategy.calculateVolume(density);
    }
}

class MyContents {
    // built via observer
    Double density;
    MyContents( Double density ) {
        this.density = density;
    }
    public Double myDensity() {
        return density;
    }

    // plugged in at the end.
    VolumeStrategy strategy;
    public void setStrategy(VolumeStrategy strategy) {
        this.strategy = strategy;
    }
    public VolumeStrategy myStrategy() {
        return strategy;
    }
}

public class Test {
    public static void main(String[] args) {
        // all those can be static 
        VolumeStrategy       smallStrategy  = new SmallVolumeStrategy();
        VolumeStrategy       bigStratetgy   = new BigVolumeStrategy();
        ContainerDirector    director       = new ContainerDirector();

       // from the GUI
       Double        density       = 15.0;
       MyContents    contents      = new MyContents( density );
       // building this contents ...
       // ... time to submit, we know what strategy to use
       contents.setStrategy(smallStrategy);

       // can turn contents into result without needing to know anything about it.
        Double       results       = director.myResult( contents );
        System.out.println( "Use this result: " + results );
    }
}