javascript - 在这种情况下,比调解器模式更好的方法来解耦小部件?

标签 javascript design-patterns mediator

我试图弄清楚在某种情况下应该遵循哪种模式。我有一个网络应用程序,它由几个主要的小部件组成,这些小部件以某种方式相互交互。小部件遵循模块模式。

让代码说话:

MyApp.Widgets.MainLeftBox = (function(){
    var self = {};

    self.doSomething = function(){
        var certainState = MyApp.Widgets.MainRightBox.getCertainState();
        if (certainState === 1){
            console.log(‘this action happens now’);
        }
        else {
             console.log(‘this action can’t happen because of a certain state in My.App.Widgets.MainRightBox’);
        }
    } 
    return self;
})();

正如你所看到的,我在这里有紧密的耦合。众所周知,紧耦合是邪恶的。 (除非您找到了唯一的!;-))

我知道通过遵循发布-订阅/自定义事件模式可以实现很多解耦。但这更适合 A 开始某件事而 B 可以使用react的情况。但我有一种情况,A 独立启动某件事,但需要检查 B 的某个状态才能继续。

当我努力实现可维护性时,我正在寻找摆脱这个 hell 的方法。

我首先想到的是中介者模式。

但是,我的代码仍然是这样的:

MyApp.Widgets.MainLeftBox = (function(mediator){
    var self = {};

    self.doSomething = function(){
        var certainState = mediator.getCertainState();
        if (certainState === 1){
            console.log(‘this action happens now’);
        }
        else {
             console.log(‘this action can’t happen because of a certain state in mediator’);
        }
    } 
    return self;
})(MyApp.Mediator);

这样好一点,因为 Widget 不直接通信,而是通过中介器间接通信。

但是,我仍然觉得我做错了,必须有更好的方法来实现部件之间的解耦。

编辑

让我总结一下到目前为止的情况!

总的来说,我确实喜欢分离 View 的 MVC 方法!然而,这个例子更像是复杂的模块。从视觉意义上来说,这些并不一定是“盒子”。这样描述起来更容易。

另一个给定的事实应该是,A 独立启动一个操作,然后需要检查某些状态。它不能订阅 B 的状态更改并提供操作,也可以不提供操作。它必须像 A 独立启动它,然后需要检查某个状态。将此视为 B 需要执行的一些复杂操作。

因此,我想出了自定义事件/回调/中介方法的混合体,其中有一些我非常喜欢的东西。

1.) 一个模块不知道任何其他模块
2.) 模块也不知道中介者
3.) 依赖于某些外部状态的模块只知道它依赖于某些外部状态 - 而不是更多
4.) 模块实际上并不关心将提供这种特定状态
5.) 模块可以确定是否已提供某种状态
6.) 请求管道是直接的。换句话说,该模块是该操作的启动者。它不只是订阅状态更改事件(记住 A 启动操作,然后需要来自 B(或某处)的状态

我在这里发布了一些示例代码,还提供了一个 jsFiddle:http://jsfiddle.net/YnFqm/

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
</head>
<body>
<div id="widgetA"></div>
<div id="widgetB"></div>
<script type="text/javascript">

var MyApp = {};

(function (MyApp){

    MyApp.WidgetA = function WidgetA(){

        var self = {}, inner = {}, $self = $(self);

        //init stuff
        inner.$widget = $('#widgetA');
        inner.$button = $('<button>Click Me!</button>')
                            .appendTo(inner.$widget)
                            .click(function(){self.doAction();});


        self.doAction = function(){
            //Needs state from WidgetB to proceed

            /* Tight coupling
            if (MyApp.WidgetB.getState() == 'State A'){
                alert('all fine!');
            }
            else{
                alert("can't proceed because of State in Widget B");
            }
            */

            var state;
            $self.trigger('StateNeeded',function(s){state = s});
            if (state == 'State A'){
                alert('all fine!');
            }
            else{
                alert("can't proceed because of State in Widget B");
            }                   
        };

        return self;
    };

    MyApp.WidgetB = function WidgetB(){

        var self = {}, inner = {};

        //init stuff
        inner.$widget = $('#widgetB');
        inner.$button = $('<button>State A</button>')
                            .appendTo(inner.$widget)
                            .click(function(){
                                var buttonState = inner.$button.text();
                                if (buttonState == 'State A'){
                                    inner.$button.text('State B');
                                }
                                else{
                                    inner.$button.text('State A');
                                }
                            });


        self.getState= function(){
            return inner.$button.text();
        };

        return self;
    };

    MyApp.Mediator = (function(){
        var self = {}, widgetA, widgetB;

        widgetA = new MyApp.WidgetA();
        widgetB = new MyApp.WidgetB();

        $(widgetA).bind('StateNeeded', function(event, callback){
            //Mediator askes Widget for state
            var state = widgetB.getState();
            callback(state);
        });

        return self;
    })();

})(MyApp);

</script>
</body>
</html>

最佳答案

您应该查看 Addy Osmani Patterns For Large-Scale JavaScript Application Architecture 发表的关于大型 JS 应用程序的精彩文章这是代码示例 Essential js design patterns

关于javascript - 在这种情况下,比调解器模式更好的方法来解耦小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4275070/

相关文章:

javascript - Angular - 是 other 的子元素

javascript - 为什么即使条件为真也会执行 else block ?

java - 服务接口(interface)和服务实现类spring的代码架构

javascript 中介者 vs 观察者

java - 使用eclipse和scene builder将数据从一个选项卡发送到javafx 8中的另一个选项卡

java - 如何克服 GUI 调解器中的并发修改异常?

javascript - 为什么 AFTERCommandExec 不会在 CKEditor 4 中触发?

javascript - 如何制作像地铁一样的水平滚动?

php - dao模式和关系

c++ - 错误 : no match for ‘operator==’ in ‘boiler::uniqueInstance == 0l’