将业务逻辑和表现逻辑分离的最佳方式是什么?

5

我希望创建一个既可以本地运行又可以在线上运行的游戏。

我的第一想法是创建一个接口,其中包含GUI所需的所有业务逻辑方法,然后实现网络和本地两种方式。

这对于请求-响应消息来说很好用。但是对于服务器发送的需要更新某些GUI组件(即JLabels)的消息呢?

我的第一个解决方案是实现监听器,在实现中每次更改都会触发一个事件。GUI将注册并相应地更改其组件。然而,在业务逻辑中调用fire events似乎有点不对劲。

我是否正确?因为我认为我不是。有什么建议吗?

谢谢。

注意:客户端是一个简单的Java Swing GUI。

2个回答

6
您所描述的可以保持模型独立于表示问题的目标,这是一件好事情。这也有助于您在设计、开发和维护模型时编写单元测试,因为您可以基于某些模型中的更改应触发特定事件来编写单元测试,而不必担心其在屏幕上看起来如何。
当然,这还使您自由地在不同的环境下进行不同的GUI设计。
关键在于事件应该是关于模型状态的更改,而不是关于预期动作/表现在表示层面上的。让表示层处理如何响应模型事件。

那我用实现监听器的方式是正确的吗?至于那个臭名昭著的MVC,我听说过,但不知道该如何实现,所以在动手之前还是问一下比较好。 - pek
我同意Joel的观点 - 这是MVC...你的视图正在监听模型并更新自己。你的模型是业务逻辑。GUI的其余部分(菜单等)与控制器部分交互(或成为控制器部分),并与模型交互以操作它。任何元素都可以独立替换,而不影响其他部分。 - frankodwyer
嗯...从来没有想过那个... ;) - pek

1

我承认我从事网站开发,所以对Swing并不是很有经验。

但我一直认为我的方法是将应用程序分成/packages/view、/model和/controller。关系是单向的:/controller会知道/model和/view,但两者都不会导入/controller或彼此的任何类。

/view层组件永远不会是JFrames;它们总是JPanel或其他适当的容器,可以根据需要组合成JFrames。每个组件都会在构造函数中初始化Listener接口的引用,并将事件处理委托给这些接口:

public class ExamplePanel extends JPanel implements ActionListener
{
    private JButton button;
    private ActionListener buttonListener;

    public ExamplePanel(ActionListener buttonListener)
    {    
        this.button = new JButton("Do Something");
        this.buttonListener = buttonListener;
        this.button.addListener(this.buttonListener);
    }

    public void actionPerformed(ActionEvent e)
    {
        this.buttonListener.actionPerformed(e);
    }
}

这种安排与依赖注入很搭配,因为现在控制器可以选择使用该Listener接口的本地或远程实现,在不影响客户端的情况下改变行为。

我承认我从未完全跟随它。

Spring团队有一个丰富的Swing客户端模块,但似乎已经不再受欢迎了。看起来他们已经决定采用BlazeDS方向作为丰富客户端的更好选择。但也许你可以从他们的方法中获得一些设计思路。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接