gpt4 book ai didi

ruby - 用 Ruby 替换运行时实现

转载 作者:数据小太阳 更新时间:2023-10-29 07:05:26 25 4
gpt4 key购买 nike

Ruby 中的依赖注入(inject)框架几乎已被宣布为不必要。贾米斯·巴克 (Jamis Buck) 去年在他的 LEGOs, Play-Doh, and Programming 中写到了这一点。博文。

普遍接受的替代方案似乎是使用某种程度的构造函数注入(inject),但只是提供默认值。

class A
end

class B
def initialize(options={})
@client_impl = options[:client] || A
end

def new_client
@client_impl.new
end
end

这种方法对我来说很好,但它似乎缺少更传统设置的一件事:一种在运行时基于某些外部开关替换实现的方法。

例如,使用依赖注入(inject)框架我可以做这样的事情(伪 C#):

if (IsServerAvailable)
container.Register<IChatServer>(new CenteralizedChatServer());
else
container.Register<IChatServer>(new DistributedChatServer());

这个例子只是根据我们的中心化服务器是否可用注册了一个不同的IChatServer实现。

由于我们仍然只是使用 Ruby 中的构造函数,因此我们无法通过编程控制所使用的依赖项(除非我们自己指定每个依赖项)。 Jamis 给出的示例似乎非常适合使类更易于测试,但似乎缺乏替代的便利。

我的问题是,您如何在 Ruby 中解决这种情况?我愿意接受任何答案,包括“你只是不需要那样做”。我只想了解 Ruby 对这些问题的看法。

最佳答案

除了构造函数替换之外,您还可以将信息存储在实例变量(“属性”)中。从你的例子:

class A
end

class B
attr_accessor :client_impl

def connect
@connection = @client_impl.new.connect
end
end

b = B.new
b.client_impl = Twitterbot
b.connect

您还可以允许依赖项作为方法的选项可用:

class A
end

class B
def connect(impl = nil)
impl ||= Twitterbot
@connection = impl.new.connect
end
end

b = B.new
b.connect

b = B.new
b.connect(Facebookbot)

您还可以混合搭配技巧:

class A
end

class B
attr_accessor :impl

def initialize(impl = nil)
@impl = impl || Twitterbot
end

def connect(impl = @impl)
@connection = impl.new.connect
end
end

b = B.new
b.connect # Will use Twitterbot

b = B.new(Facebookbot)
b.connect # Will use Facebookbot

b = B.new
b.impl = Facebookbot
b.connect # Will use Facebookbot

b = B.new
b.connect(Facebookbot) # Will use Facebookbot

基本上,当人们谈论 Ruby 和 DI 时,他们的意思是该语言本身足够灵活,无需特殊框架即可实现任意数量的 DI 风格。

关于ruby - 用 Ruby 替换运行时实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1081717/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com