Алексей Плуталов, Злые марсиане
Чем сложнее класс или компонент, тем меньше должно быть внешних связей.
Важный принцип используемый для уменьшения связанности кода
Паттерн скрывающий процессы связанные с получением модуля с сильным уровнем абстракции
Реализуется в виде центрального реестра ресурсов, возвращающего нужную информацию по запросу
var Connection = function () {
this.logger = require("logger")();
/* реализация логики */
}
Процесс предоставления внешней зависимости программному компоненту
// adapter - клиент хранилища (например, REST)
// serializator - сериализатор данных
var Resource = function (adapter, serializator) {
this.adapter = adapter;
this.serializator = serializator;
};
var Resource = function ( ) { };
Resource.prototype.setAdapter = function (adapter) {
this.adapter = adapter;
};
Resource.prototype.setSerializator = function (srl) {
this.serializator = srl;
};
var Injectable = function ( ) { };
Injectable.prototype.inject = function (name, dep) { };
var Resource = function ( ) { Injectable.apply(this); };
Resource.prototype.inject = function (name, dep) {
this[name] = dep;
};
Object.prototype.inject = function (name, dep) {
this[name] = dep;
};
var resource = new Resource();
resource.inject(adapter, serializer);
jQuery.fn.pluginName = function ( ) {
this; // jQuery объект с выборкой элементов
};
app.use(function * ( ) {
this; // Koa Context
this.request; // Koa Request
this.response; // Koa Response
});
Программный каркас реализующий DI, и упрощающий его использование
Многие фреймворки являются реализацией IoC-container
Ember.js предоставляет IoC-container, и две реализации DI:
App.SessionController = Ember.Controller.extend({
isSignedIn: false
});
App.IndexController = Ember.Controller.extend({
needs: [ "session" ],
isSignedIn: function ( ) {
return this.get("controllers.session.isSignedIn");
}.property("controllers.session.isSignedIn");
});
App.SignInController = Ember.Controller.extend({
needs: [ "session" ],
isSignedIn: Ember.computed.alias("controllers.session.isSignedIn"),
actions: {
signIn: function ( ) {
this.set("isSignedIn", true);
}
}
});
Использование DI в Ember.js сводится к двум методам:
register
— регистрация провайдераinject
— внедрение зависимостиvar Logger = Ember.Object.extend({
write: function (msg) {
console.log(msg);
}
});
application.register("logger:console", Logger);
var Logger = Ember.Object.extend({
write: function (msg) {
console.log(msg);
}
});
application.register(
"logger:console", Logger, { singleton: false }
);
App.register("logger:console", function (msg) {
console.log(msg);
}, {
instantiate: false
});
Ember.Application.initializer({
name: "logger",
initialize: function (container, application) {
application.register("logger:console", function (msg) {
console.log(msg);
}, { instantiate: false });
application.inject("route", "logger", "logger:console");
}
});
App.create();
App = Ember.Application.create({
Resolver: Ember.DefaultResolver.extend({
resolveTemplate: function (parsedName) {
var resolvedTemplate = this._super(parsedName);
if (resolvedTemplate) {
return resolvedTemplate;
}
return JST[parsedName] || Ember.TEMPLATES["not_found"];
}
});
});
resolve[Type]
— разрешение типа зависимостиresolveOther
— разрешение всех остальных зависимостейКастомизацию разрешения зависимостей используют