Я пытаюсь выяснить, какой шаблон следует придерживаться в определенной ситуации. У меня есть веб-приложение, которое состоит из нескольких основных виджетов, которые так или иначе взаимодействуют друг с другом. Виджеты следуют шаблону модуля.
Чтобы код говорил:
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;
})();
Как видите, у меня здесь сильная связь. Как мы все знаем, тесная связь - это зло. (За исключением случаев, когда вы нашли один-единственный!; -))
Я знаю, что развязки можно достичь, следуя шаблону pub-sub / custom event. Но это лучше подходит для ситуаций, когда А начинает что-то, и В может реагировать. Но у меня есть ситуация, когда A запускает что-то независимо, но для проверки необходимо проверить определенное состояние из B.
Поскольку я стремлюсь к ремонтопригодности, я ищу выход из этого ада.
Первое, что пришло мне в голову, - образец посредника.
Но все же мой код будет выглядеть так:
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);
Это немного лучше, потому что виджеты не общаются напрямую, а косвенно через посредника.
Однако я все еще чувствую, что я делаю это неправильно, и должен быть лучший способ добиться отделения виджетов друг от друга.
EDIT
Позвольте мне подвести итоги!
В общем, мне нравится подход MVC разделения представлений! Однако, думайте об этом примере как о сложных модулях. Это не обязательно должны быть «коробки» в визуальном смысле. Просто так проще описать.
Еще одним фактом должно быть то, что A запускает действие независимо и тогда ему нужно проверить состояние. Он не может подписаться на изменение состояния B и предоставлять действие или нет. Это должно быть похоже на то, как А запускает его независимо , а затем необходимо проверить определенное состояние. Думайте об этом как о некоторой сложной операции, о которой нужно попросить 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>