• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

[原创]20行ruby代码实现依赖注入框架

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

我需要依赖注入

业余时间开发的娱乐项目 (为了练习使用ruby语言)

遵循SRP原则,业务逻辑拆分由各个service类型提供,假设存在如下几个类型

  • GameService 封装主要游戏业务逻辑
  • UserService 维护用户信息
  • PlayerService 封装当前玩家信息及业务逻辑
  • ChatService 封装聊天业务逻辑

Service之间存在依赖关系,例如
PlayerService 依赖 UserService中的方法
PlayerService 依赖 ChatService中的方法
GameService 又依赖其他三个Service中的方法

最佳解决方案,实现依赖注入

Ruby实现依赖注入 第一版 快速实现

def init_dependency_injection
  map = {}

  Kernel.send :define_method, :get_instance do |clazz|
    instance = map[clazz]
    if instance.nil?
      instance = clazz.new
      map[clazz] = instance
    end
    instance
  end
end

init_dependency_injection方法在程序入口处调用

代码解析

初始化ioc容器 map = {}

向内核类型中添加扩展方法get_instance(所谓的monkey hook),

get_instance方法接受参数clazz,表示一个类型,方法中创建该类型对象并添加对象值ico容器中

PlayerService中如何使用UserService,代码如下

class PlayerService
  def initialize
    user_service = get_instance(UserService)
    user_service.do_sth
  end
end

Ruby实现依赖注入 第二版 改进

我觉得使用上还可以更方便些,类似spring mvc中通过注解进行依赖注入,向Kernal中补充autowired方法

def init_dependency_injection
  map = {}

  Kernel.send :define_method, :get_instance do |clazz|
    instance = map[clazz]
    if instance.nil?
      instance = clazz.new
      map[clazz] = instance
    end
    instance
  end

  Kernel.send :define_method, :autowired do |*classes|
    classes.each do |clazz|
      underscore_class_name = clazz.name.to_s.gsub(/(.)([A-Z])/, '\1_\2').downcase
      instance_variable_set("@#{underscore_class_name}", get_instance(clazz))
    end
  end
end

使用方式如下

class PlayerService
  def initialize
    autowired(UserService)
  end

  def x
    @user_service.do_sth
  end
end

对于GameService依赖多个Services,同样简单,如下

class GameService
  def initialize
    autowired(UserService, PlayerService, ChatService)
  end
  
  def x
    @user_service.do_sth
    @player_service.do_sth
    @chat_service.do_sth
  end
end

程序中任何类型中,都可以使用autowired方法注入所需类型对象,自动定义实例变量,便于使用

autowired方法代码解析

  1. 获取类型集合,遍历之
  2. 获取类名,由CamelCase转换为under_score,作为实例变量名
  3. 通过instance_variable_set设置实例变量,值通过get_instance获取

perfect!


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Ruby中puts,print,p的区别发布时间:2022-07-14
下一篇:
ruby学习笔记(3)-新手入门发布时间:2022-07-14
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap