Ruby Case语句的替代方案

Phi*_*ell 3 ruby switch-statement

我目前正在使用Ruby为银行管理系统编写程序.该系统的一个功能是它可以创建一个新帐户,帐户可以是六种类型之一.

我的控制器中有以下方法来满足此功能:

def create_account(type, holder)
  case type
  when :current  then CurrentAccount.new(holder, @account_number)
  when :savings  then SavingsAccount.new(holder, @account_number)
  when :business then BusinessAccount.new(holder, @account_number)
  when :ir       then IRAccount.new(holder, @account_number)
  when :smb      then SMBAccount.new(holder, @account_number)
  when :student  then StudentAccount.new(holder, @account_number)
  end
end
Run Code Online (Sandbox Code Playgroud)

这些账户中的每一个都从基础账户继承,最终将包含个人属性,例如利率,透支等.

虽然这是功能性的,并提供了所需的结果,但感觉有点冗长.但是我想不出任何明显的重构方法.

欢迎任何建议......

Nei*_*ter 6

我假设在某些时候系统或最终用户有效地选择文本类型,您需要将其转换为要使用的类.否则,您可以编写简单引用并实例化正确类的调用代码.

您可以通过定义符号type和类之间的映射来使您拥有更清洁的东西.所以你可以在以下范围内做到这一点create_account:

ACCOUNT_CLASS_FOR = Hash[
  current:  CurrentAccount,
  savings:  SavingsAccount,
  business: BusinessAccount,
  ir:       IRAccount,
  smb:      SMBAccount,
  student:  StudentAccount
]

def create_account(type, holder)
  if account_class = ACCOUNT_CLASS_FOR[ type ]
    account_class.new( holder, @account_number )
  else
    raise "Bad account type #{type}"
  end
end
Run Code Online (Sandbox Code Playgroud)

这减少了重复的代码,并使符号名称和匹配的Ruby类之间的映射更加明确.如果您需要在其他地方应用或测试转换,您可以在不重复自己的情况下使常量在不同范围内可用.

你可以通过让每个班级都知道自己的标签来使这个更清洁

class CurrentAccount
  def self.label
     :current
  end
end
Run Code Online (Sandbox Code Playgroud)

然后你可以有这样的东西:

ALLOWED_ACCOUNT_CLASSES = [CurrentAccount,SavingsAccount,BusinessAccount, # etc.

ACCOUNT_CLASS_FOR = Hash[
  ALLOWED_ACCOUNT_CLASSES.map { |klass| [klass.label, klass] }
]
Run Code Online (Sandbox Code Playgroud)

请注意,klass在这里使用拼写错误的变量以避免与Ruby的class关键字冲突是很常见的做法,但您也可以使用account_class