揭开全球阶级运营商设计模式的神秘面纱

时间:2017-08-26 21:34:43

标签: ruby architecture

我正在通过一个关于"高级课程方法的在线代码训练营教程"当我发现奇怪的事情。首先定义 Person 类,特别是 #normalize_names 方法。基本上,此方法会遍历 @@ all 中存储的 Person 类的每个实例,并将存储在 person.name 中的名字和姓氏大写

class Person
  attr_accessor :name
  @@all = []
    def self.all
     @@all
    end

  def initialize(name)
    @name = name
    @@all << self
  end

  def self.normalize_names
    self.all.each do |person|
      person.name = person.name.split(" ").collect{|w| w.capitalize}.join(" ")
    end
  end
end

然后教程解释说&#34;鉴于人名的复杂程度是多么复杂,我们实际上应该将[方法]封装到 Person 实例中。&#34;因此,随后 #normalize_names 方法被重构为如此。

def normalize_name
    self.name.split(" ").collect{|w| w.capitalize}.join(" ")
end

def self.normalize_names
    self.all.each do |person|
      person.name = person.normalize_name
    end
end

因此&#34;简化了对所有人的全局数据起作用的类方法,并将实际规范化委托给原始实例。这是全球集团运营商的常见模式。&#34;这为什么常见?规范化名称的复杂性如何优于这种设计模式?

1 个答案:

答案 0 :(得分:1)

缺少第一个normalize_names实现的明显之处是,只更新一个人的方法?一个选项是编写另一个类方法,该方法接受单个人实例。为了分离关注点,可以将其分为两种方法:

def self.normalize_names
  # note that 'self' can be omitted in most cases
  all.each { |person| normalize_name person }
end

def self.normalize_name(person)
  # note use of proc shorthand to shorten collect { |x| x.capitalize }
  person.name = person.name.split(" ").collect(&:capitalize).join(" ")
end

现在至少有一种方法可以更新一个人(如果需要的话)。虽然没有确定的要求使用实例与类的方法,但可能需要稍微简洁的API,例如, person.normalize_name而非Person.normalize_name(person)。说实话,这可能是将其转移到实例方法的最大原因:

def self.normalize_names
  all.each &:normalize_name
end

def normalize_name
  # note that attr_writers ("self.name =") are one of the few places you need 
  # "self", to differentiate it from variable assignment
  self.name = name.split(" ").map(&:capitalize).join " "
end