DIMJim Weirich开发的极简依赖注入框架。

依赖注入通过创建容器来帮助你组织应用的对象初始化代码。当应用中的对象需要访问其他对象或资源的时候,它要求容器来提供(通过惰性加载的代码区块)。

依赖注入

例子

lib.init.rb中加入如下代码:(Rails应用使用config/initializers/container.rb

require "dim"
require "logger"
require 'game'
require 'event_handler'
require 'transmitter'

ServerContainer = Dim::Container.new

ServerContainer.register(:transmitter) { |c| Transmitter.new(c.logger) }

ServerContainer.register(:event_handler) do |c|
  eh = EventHandler.new
  eh.transmitter = c.transmitter
  eh.logger = c.logger
  eh
end

ServerContainer.register(:listening_host) { "0.0.0.0" }
ServerContainer.register(:listening_port) { "8080" }

ServerContainer.register(:game) do |c|
  game = Game.new
  game.logger = c.logger
  game.event_handler = c.event_handler
  game.host = c.listening_host
  game.port = c.listening_port
  game
end

ServerContainer.register(:root_dir) do |c|
  Pathname.new(File.expand_path(File.dirname(__FILE__) + "/.."))
end

ServerContainer.register(:log_file_path) do |c|
  "#{c.root_dir}/log/#{c.environment}.log"
end

ServerContainer.register(:logger) do |c|
  Logger.new(c.log_file_path)
end

# attempts to read ENV["API_PASSWORD"], otherwise makes sure that the parent container has
# a service named api_password registered
ServerContainer.register_env(:api_password)

当你需要引用logger对象的时候,只需:

ServerContainer.logger.info("I didn't have to setup my own logger")

如果你需要访问game实例(初始化时已经创建好了):

current_game = ServerContainer.game

如果你不喜欢使用全局常量ServerContainer,你可以将ServerContainer本身注入对象:

World.new(GameContainer)

更多背景

Jim亲自撰写了一篇文章,介绍使用依赖注入的理由和原理。他的演示文档也值得一看。

许可

Dim以MIT许可发布。

Jim Weirich


编译 SegmentFault


weakish
24.6k 声望844 粉丝

a vigorously lazy deadbeat with matured immaturity