【问题标题】:Java MVC - Doesn't feel like I get itJava MVC - 不觉得我明白
【发布时间】:2010-11-10 08:35:11
【问题描述】:

作为一个编程初学者,当我遇到墙壁时,它总是让我感到困扰。 目前,其中一堵墙是相互依赖的对象。

正如您在我的问题历史中看到的那样,我目前正在开发一个黑莓应用程序,我在其中实现了我称之为 MVC 模式的东西,但这并不是我认为的本意。

你看,一个新手程序员,你看这个图这样的摘要,你就会明白它背后的想法。但实施它是另一回事。

alt text http://www.ibm.com/developerworks/wireless/library/wi-arch6/theoretical.gif

请不要停止阅读 :) 我正在向您展示我的一些代码,其中包含一些特定于黑莓的内容,但您应该看看我在做什么。

我的应用程序的主要入口点

public class ContactManager extends UiApplication
{
    private static ContactManagerMainScreenModel MainScreenModel = new ContactManagerMainScreenModel();
    private static ContactManagerMainScreen MainScreenView = null;

    public static void main(String[] args)
    {
        new ContactManager().enterEventDispatcher();
    }
    public ContactManager()
    {   
        MainScreenView = new ContactManagerMainScreen(MainScreenModel);
        // Displays the Splashscreen then opens the Mainscreen 
        new SplashScreen(UiApplication.getUiApplication(), MainScreenView);
    }
}

主屏幕模型

public class ContactManagerMainScreenModel
{
    ContactManagerMainScreen v;
    // Loading Local Storage
    LocalContactStorage LocalContactStorage = new LocalContactStorage();

    // Define Data List
    private Vector vContacts_Favorites;

    public void register(ContactManagerMainScreen v)
    {
        this.v = v;
    }
    // Retrieve Favorite Contacts from Persistant Storage
    public Vector getFavoriteContactsFromLocalStorage()
    {
        vContacts_Favorites = LocalContactStorage.getFavoriteContactsFromLocalStorage();
        return vContacts_Favorites;
    }
    // Put Retrieve Favorite Contacts from Persistant Storage
    public void saveFavoriteContactsToLocalStorage()
    {
        LocalContactStorage.saveFavoriteContactsToLocalStorage(vContacts_Favorites);
    }
}

MainScreenController

public class ContactManagerMainScreenController 
{
    private ContactManagerMainScreenModel _model = null;
    private ContactManagerMainScreen _view = null;

    public ContactManagerMainScreenController(ContactManagerMainScreen view, ContactManagerMainScreenModel model)
    {
        this._model = model;
        this._view = view;
    }

    public void HideFavoriteList()
    {
        if( this._view._ContactList.getManager() != null)
        {
            this._view._ContactList.getManager().delete(this._view._ContactList);
        } else
        {
            this._view._bottom_box.add(this._view._ContactList);
        }
    }
}

还在吗?好吧……

我的问题是,我想使用控制器来更改 UI 元素,例如显示弹出框、隐藏某些东西或其他东西。

但是所有这些 UI 元素都在 View 中定义(此处为 ContactManagerMainScreen),因此必须向 Controller 提供对 View 的引用。这导致我的共同依赖对象痛苦。

在声明视图之前我无法创建控制器。如果不要求允许控制器更改 UIElements,那是没有问题的(如图所示)。

我现在做的是视图创建控制器

controller = new ContactManagerMainScreenController(this , model);

这有意义吗?我想了解这种模式,所以将我的代码称为垃圾或任何你喜欢的东西:) 我只是想学习一些东西。

附:请原谅我的英语不好:)

【问题讨论】:

    标签: java model-view-controller design-patterns java-me


    【解决方案1】:

    MVC 是一个有趣的抽象,但存在一些问题。

    实际上,控制器和视图通常是成对的——尽管理论上你应该能够在没有另一个的情况下替换其中的一个,但实际上不同视图的接口机制是如此不同,以至于控制器和视图结合在一起。

    我见过的有关 Java 的最佳描述是视图是您的摆动组件,因此您的视图代码部分只是将这些组件放在屏幕上。

    您的控制器是该类的其余部分、侦听器以及与视图交互的其余代码。

    我的建议是不要太担心隔离视图和控制器,但也就是说,我完全落后于在模型和视图/控制器之间保持非常强的分离。

    编辑/高级: 我使用了一种模式,其中控制器和视图是隔离的,它更灵活,但往往需要做更多的工作。我认为 Struts 使用了绑定模型——如果您想了解一些抽象技术,您可以查看那里或搜索有关“绑定”摇摆控件的内容。

    【讨论】:

    • (如果有人可以说明如何合理地分离视图和控制器,我会非常感兴趣。)
    • 感谢您的回答比尔。正如您所意识到的,我的一个恐惧是“编写糟糕的代码”。认为我的实现是可以接受的吗?还有一件事:“[...] 视图是您的摆动组件,而您的视图代码只不过是将这些组件放在屏幕上。[...]”您的意思是“[...] 您的控制器代码是什么都没有[...]”?
    • 可以将视图和控制器分开,但恕我直言,不像在 Web 应用程序中那样干净。
    • 是的,我在想控制器的时候用过几次模型这个词。以为我在审查时抓住了他们。你的代码看起来也很好——我见过更糟的。如果您必须开发 50 个屏幕,每个屏幕上都有数十个控件,我会说认真考虑创建一个使用绑定的系统,但是对于几个屏幕,传统技术可以正常工作。
    • @Praveen 并非如此,在网络应用程序上,您的“视图”是“网络”。如果您将其切换到另一个视图(例如摇摆控件、数据库前端或 CLI,我敢打赌您也将替换大部分控制器代码)。 MVC 在网络上似乎更容易,因为您假设您从不切换视图。
    【解决方案2】:

    从我的角度来看,这是我第一次尝试在我的第一个桌面应用程序中分离我的模型、视图和控制器时遇到的问题。

    对于 Web 应用程序,MVC 模式非常自然地适合 Web 的固有性质,但不幸的是,不可能将纯 MVC 模式适合桌面应用程序,因为操作系统在通知中扮演着与生俱来的角色。这通常会导致您在图表中显示的模式被实现。

    但是,我认为您展示的模式确实需要像这样实现(在与 Java 短暂接触后,我已经切换到 .NET,所以请记住这一点):

    public class ContactManagerMainScreenModel
    {
        ContactManagerMainScreen v;
        // Loading Local Storage
        LocalContactStorage LocalContactStorage = new LocalContactStorage();
        // Favorite list
        boolean showFavoritesList = true;
    
        public void register(ContactManagerMainScreen v)
        {
            this.v = v;
        }
    
        public void ShowOrHideFavoritesList()
        {
            if(showFavoritesList) 
            {
                showFavoritesList = false;
                v.RefreshView(this);
            }
            else
            {
                showFavoritesList = true;
                v.RefreshView(this);
            }
        }
    }
    

    同时控制器将负责接收用户操作。因此,如果您有一个显示“切换收藏夹”的按钮,这将导致控制器调用 _model.ShowOrHideFavoritesList()。模型会更新自己并要求视图使用它的新状态来刷新自己。

    视图现在将摆脱对控制器的依赖。

    【讨论】:

    • 再次感谢您的回答。您的实现将导致直接控制 UI 本身的模型。你会建议放弃整个控制器吗?
    • 不,请阅读我在代码后的最后两段。控制器负责处理所有用户通知。这是另一个例子。假设用户单击“添加新联系人”,控制器将负责调用 _model.AddNewContact(string firstName, string lastName)。然后模型会将这个联系人添加到它自己的内部状态中,然后在视图上调用 RefreshView(this)。
    • 我的意思是控制器仍然负责捕获所有用户通知,然后决定如何更新模型。然后模型总是在视图上调用 RefreshView(this),然后重新显示自己...
    【解决方案3】:

    我认为这张图不是很好,可能会让事情变得更加混乱。

    控制器应该负责将模型提供给视图。模型应该只包含数据的简单访问器。与模型交互或更改任何值的任何需要都应通过控制器进行。

    这样,视图只需要知道如何向用户呈现/呈现模型。所以对模型的任何操作——比如saveFavoriteContactsToLocalStorage()——应该是控制器的方法,而不是视图类。此外,控制器不应该需要对要构造的视图的引用——我认为这最终会颠倒整个 MVC 模式的预期顺序。

    【讨论】:

    • 我相信他的图表是正确的。问题是 MVC 不是一个好的抽象,每个工具包都在调整它以使其适合他们设计的方式。有些做得很好,有些则不太好——可以肯定的一件事是,如果你改变视图,你最终会改变控制器(这与理论背道而驰)。
    • 也许吧。我只是非常熟悉在 Web 上下文中使用 MVC,在这种情况下,控制器将简单地返回要使用的视图和模型(如在 Spring MVC 中)。我想它在桌面上可能会完全不同。
    【解决方案4】:

    我同意 Bill K 的观点。标准 MVC 在处理富客户端时并不重要。当将 Web 应用程序编写为事件(浏览器中的点击)与您的视图(HTML 渲染)完全不同时,这是一个很好的模型。

    使用标准 GUI,更好的模型是 PAC(演示/抽象/控制)。这里的表示是(视图+事件处理程序),控制器管理表示和抽象之间的交换。抽象就是你的商业模式。

    这样你就有了一个控制器来管理 GUI 部分(视图 + 用户事件)和你的抽象之间的链接。您开发的任何 GUI 都有一个 PAC 代理,并且它们之间有一个清晰的分离。

    另一篇关于 PAC 的比 MVC 更好的文章:HMVC。相当古老,但它很实用,有助于理解事物。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      • 2013-11-06
      • 2012-05-01
      • 1970-01-01
      • 2014-01-25
      相关资源
      最近更新 更多