Skip to content

Instantly share code, notes, and snippets.

@ryancheung
Created November 25, 2012 02:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryancheung/4142129 to your computer and use it in GitHub Desktop.
Save ryancheung/4142129 to your computer and use it in GitHub Desktop.
specification pattern implementation
# encoding: utf-8
class TagSpec
attr_reader :tag
attr_accessor :result
def initialize(tag)
@tag = tag
end
def match?(tag_collection)
tag_collection.include?(tag)
end
def and(other)
other = TagSpec.new(other) unless other.kind_of?(TagSpec)
AndTagSpec.new(self, other)
end
def or(other)
other = TagSpec.new(other) unless other.kind_of?(TagSpec)
OrTagSpec.new(self, other)
end
def not
NotTagSpec.new(this)
end
end
class AndTagSpec < TagSpec
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def match?(tag_collection)
left.match?(tag_collection) && right.match?(tag_collection)
end
end
class OrTagSpec < TagSpec
attr_reader :left, :right
def initialize(left, right)
@left = left
@right = right
end
def match?(tag_collection)
left.match?(tag_collection) || right.match?(tag_collection)
end
end
class NotTagSpec < TagSpec
attr_reader :wrapper
def initialize(wrapper)
@wrapper = wrapper
end
def match?(tag_collection)
!wrapper.match?(tag_collection)
end
end
class OrderedCompositeSpec < TagSpec
def initialize
@specs = []
end
def add(tag_spec, priority)
@specs << [tag_spec, priority]
end
def match?(tag_collection)
ordered_specs = @specs.sort { |x, y| x.last <=> y.last }
ordered_specs.each do |spec, _|
if spec.match?(tag_collection)
self.result = spec.result
return true
end
end
false
end
end
spec1 = TagSpec.new("有伤病").and("没时间运动")
spec1.result = { default: "针对您无法运动/没时间运动的情况,我们帮您制定了一个能将运动融入生活的计划。培养规律的饮食习惯对于您的减重计划尤为重要。由于缺乏足够的有氧运动,减重速度必定会受影响,因此,只要时间允许尽量安排每周4~5次的有氧运动,用以提升减重效果。接下来,建议多关注围度变化,而不仅仅是体重的变化。让我们开始全新的NICE轻松、快乐减重之旅吧!" }
spec2 = TagSpec.new("重度肥胖").and("肥胖")
spec2.result = { default: "您目前的BMI远超健康上限,减重不是一两天的事情,坚定信心,但不要操之过急。建议您用3个月左右的时间让体重稳定的减轻10kg,同时关注腰围的变化,这对于保护心脑血管健康非常重要。相信我们只要认真努力,一定会有很好的成绩,马上就开始崭新的NICE健康、快乐减重之旅吧!" }
spec3 = TagSpec.new("超重")
spec3.result = { default: "您目前的BMI已经超出健康范围,减肥的第一步是把体重控制在健康体重范围*斤以内,再减至*斤左右(BMI=22 时对应的体重,此时健康达到比较好的水平),然后可向标准体重**斤前进;同时在此过程中需关注身体围度的变化。" }
composite_spec = OrderedCompositeSpec.new
composite_spec.add(spec1, 0)
composite_spec.add(spec2, 1)
composite_spec.add(spec3, 1)
if composite_spec.match?(["没时间运动", "超重", "有伤病"])
puts composite_spec.result[:default]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment