Builder class 负责将所有的部件瓶装于一个复杂的对象中。
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
14.2 生成器模式 UML 类图:
14.3应用场景:
1 、当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2 、当构造过程必须允许被构造的对象有不同的表示时。
14.4生成器模式分析与实现(ruby 描述):
class Computer attr_accessor :display attr_accessor :motherboard attr_accessor :drives def initialize(display=:crt, motherboard=Motherboard.new, drives=[]) @motherboard = motherboard @display = display @drives = drives end end class CPU end class TurboCPU < CPU end class BasicCPU < CPU end class Motherboard attr_accessor :cpu attr_accessor :memory_size def initialize(cpu=BasicCPU.new,memory_size=1000) @cpu = cpu @memory_size =memory_size end end class Drive attr_reader :type attr_reader :size attr_reader :writable def initialize(type, size, writable) @type = type @size = size @writable = writable end end # # 这是我们来创建一台非常好的计算机 # motherboard = Motherboard.new(TurboCPU.new,4000) drives = [] drives << Drive.new(:hard_drive, 200000,true) drives << Drive.new(:hard_drive, 200000,true) drives << Drive.new(:hard_drive, 200000,true) drives << Drive.new(:cd, 200,true) computer = Computer.new(:lcd,motherboard,drives) # # 这时,我们可能还没有发现问题,因为我们才刚刚创建了一台电脑,比如我们现在要开网吧,我们需要一百台点配置不同的电脑,我想大家就要挠头了 # 现在看看我们用生成器会带来什么好处吧 # class ComputerBuilder attr_reader :computer def initialize @computer = Computer.new end def turbo(has_turbo_cpu=true) @computer.motherboard.cpu = TurboCPU.new end def display=(display) @computer.display=display end def memory_size=(size_in_mb) @computer.motherboard.memory_size = size_in_mb end def add_cd(writer=false) @computer.drives << Drive.new(:cd,760,writer) end def add_dvd(writer=false) @computer.drives << Drive.new(:dvd, 4000, writer) end def add_hard_disk(size_in_mb) @computer.drives << Drive.new(:hard_work,size_in_mb,true) end end builder = ComputerBuilder.new builder.turbo builder.add_cd(true) builder.add_dvd builder.add_hard_disk(1000000000) computer = builder.computer # # 通过电脑生成器,我们可以生成我们想要的电脑的了,就想我们去组装店一样,告诉他们我们想要的配置,他们安装我的要求,不一会就帮我组装了 # 我想要的电脑,真实太棒了,在RUBY中有种魔法方法来写错的生成器,我们来看看吧 # def method_missing(name, *args) words = name.to_s.split("_") return super(name, *args) unless words.shift == 'add' words.each do |word| next if word == 'and' add_cd if word == 'cd' add_dvd if word== 'dvd' add_hard_disk if word == 'harddisk' turbo if word == 'turbo' end end builder.add_dvd_cd_harddisk # or builder.add_turbo_and_dvd_harddisk # # 魔法方法最杰出的应用是ActiveRecord中的查询方法 # Employee.find_by_ssn('123-34-333') # # Employee.find_by_firstname_and_lastname('John', 'Smith')