1

我只被允许在我正在学习的编程课程中使用私人成员,我想知道这样的事情是否可以。

public class View {
    private Model object_;
    public View(Model object) {
       object_ = object;
       //blah blah blah
    }
//blah blah blah
}

public class Controller {
    private Model object_;
    public Controller(Model object) {
       object_ = object;
       //blah blah blah
    }
//blah blah blah
}

public class MainClass {
    public static void main(String [ ] args) {
        Model m = new Model();
        Controller c = new Controller(m);
        View v = new View(m);
        //blah blah blah
    }
}

View 和 Controller 类都拥有相同的 Model 实例作为私有字段。这可以接受吗?似乎它会违反私有字段的概念。我试着问我的教授,他说没关系,但我不确定他是否理解我的问题,或者我是否理解他的回答:)

4

7 回答 7

2

关于标题问题:是的,没关系。想象一棵树,其中兄弟姐妹共享对父母的引用。这种情况相当普遍。

于 2009-11-03T23:44:50.797 回答
1

如果您查看这篇文章,您会发现理想情况下控制器位于模型和视图之间。因此,我可能会某种程度上重新组织您的依赖关系(对此存在一些分歧-见下文)

但是你的问题的答案(不管域)是你可以分享这些私人参考。理想情况下,它们应该是对接口的引用,并且可以在不更改依赖类的情况下更改实现。因此(例如)您将有一个Model接口和一个实现ModelImpl,并且共享引用的类型为Model. 然后,您可以在以后替换不同的实现,而不会影响您的大部分代码。

于 2009-11-03T23:41:46.447 回答
1

简短的回答是这很好。

更长的答案(暂时忘记 MVC,因为似乎 MVC 是这样做的一个例子,而不是问题的核心)是你必须考虑可变性。如果一个对象不是可变的(对象上的任何字段都不能改变),那么共享是一件非常好的事情,它减少了内存占用并且没有真正的缺点。

但是,如果对象是可变的,那么您必须了解更改对象的状态如何影响引用它的对象。在 MVC 中,很典型的情况是看到模型发生变化,然后最终基于此调整视图,因此您可以将其构建到设计中,但请考虑这种情况:

  private Collection myCollection; 

  public void setMyCollection(Collection someCollection) { 
       myCollection = someCollection; 
  }

这样的代码必须非常有信心,调用者不会向它传递一个随后会更改的可变集合,或者它必须允许这样做。解决上述问题的典型方法是复制 ( myCollection = new ArrayList(someCollection);)

所以总而言之,这是一种很好的常见做法,但是当对象是可变的时,你必须考虑对你的设计产生的后果。

于 2009-11-03T23:52:54.567 回答
1

简短的回答:两个不同的类没有任何问题,它们具有引用同一事物的私有成员变量。这是很常见的。

长答案:我的猜测是您的教授可能在这里谈论的是:
private Model object_是一个对象引用变量(不是原语)。因此,当您传入 object_Controller 和 View 的构造函数时,您将“链接”传递给同一实例
object_,而不是传递 object_.

是否选择将它们作为私有存储在 Controller 和 View 中是完全不同的决定。我熟悉禁止使用非私有成员变量的大学编程课程(去过那里)。他们想介绍一些面向对象的概念,例如封装(稍后),然后他们会告诉您为私有成员变量创建公共访问器和修改器。这通常是一个很好的开始原则,因为只有当你有充分的理由这样做时,才应该使用受保护的和公共的成员变量。

所以是的,这些是正确的 Java,但是这是否真的是您想要对您的代码执行的操作是另一回事(请参阅 Caleb 的回答)。

于 2009-11-03T23:54:49.143 回答
1

这可以接受吗?

是的。

似乎它会违反私有字段的概念

它没有。控制器无法从视图中更改实例,因为它是私有的。

考虑以下试图更改视图中模型的代码行:

public class Controller {
    private Model object_;
    public Controller(Model object) {
        object_ = object;
        this.object_.view.object_ = new Model(); // doesn't work.
        // or view.object_ = ....            
       //blah blah blah
    }
    //blah blah blah
}

好吧,这行不通,第一因为模型没有对视图的引用,第二,如果有它,controller则无法更改model视图中的,因为它对他来说是不可见的。

在某些情况下可能不希望共享同一个对象。例如,如果您依赖给定对象的状态并且该状态被其他对象更改,您的代码可能会失败。请参阅防御性复制这就是为什么建议使用不可变对象并限制对它的访问的原因。

但特别是在 MVC 设计模式中,共享一个正是您需要的对象,或者至少共享该对象的状态。在 MVC 中,您需要的是View了解Controller状态Model。看到相同的对象并不会降低它们的私密性(从某种意义上说,每个对象都不知道它们看到的是相同的东西),这允许低耦合

肯定会破坏对象隐私的东西会使该属性具有非私有属性,例如:

class View {
   public Model m; 
}
class Controller {
    public Model m;  
}
....
public static void main( String ... args ) { 
     Model m = ... 
     View v = new View();
     Controller c = new Controller();
     v.m = m;
     c.m = m;
}

因为不会有任何访问控制来防止发生疯狂的变化。

于 2009-11-04T00:19:57.497 回答
0

据我所知,没有严格的“私有领域法则”规定一个对象可以由多个类私有地持有。对于像不可变引用类这样的东西,多个类实例可以接收不可变引用类并将其作为私有属性保存是有意义的。

在您的示例中,Carl 是对的——视图和控制器通常应该在某些方法中将模型作为参数,而不是保留对它们的引用。所以代码看起来更像这样:

public Response handleRequest(Request request) {
    Controller c = new Controller();
    Model m = c.processRequest(request);
    View v = new View();
    Response response = v.createResponse(model);
    return response;
}
于 2009-11-03T23:41:35.073 回答
0

是的,这是可以接受的,应该使用私有字段来强制封装,如果需要,通过 getter/setter 方法控制对这些字段的访问。如果这些字段是公共的,甚至是打包的,那么外部类可能会开始依赖于您对该类的实现,这会在重构方法等方面束缚您。允许其他类访问他们应该有权访问的字段可能会导致隐私泄露。

如果模型在哪里公开。

类混乱{

模型 aModel = object_; aModel.doWhatTheHellIWantToYourModel();

}

这可以完全验证您的系统状态。

于 2009-11-03T23:43:00.283 回答