为了模拟这个问题,我们可以使用名为 Locker 和 Bag 的类,它们代表领域对象(即应用程序将处理的实际对象)。
Locker 对象可以有状态标志来确定它是哪种类型的储物柜(小型、中型或大型),Bag 对象也是如此。我们的两个类可以如下所示:
class Locker
attr_reader :type, :id
attr_accessor :bag
def initialize(id, type = nil)
raise ArgumentError, "Id not present" if id.nil?
@id = id
@type = type
@bag = nil
end
def free?
!@bag
end
def can_place(bag)
return false unless free?
case bag.type
when :small
true
when :medium
@type != :small
when :large
@type == :large
else
# invalid type
false
end
end
end
class Bag
attr_reader :type
def initialize(type = nil)
@type = type
end
end
每当您创建一个新对象(在我们的例子中为Bag.new 或Locker.new)时,都会调用initialize 方法。
所以,我们有两个域对象,但我们仍然需要一些东西来运行我们的实际程序。这可以称为任何您想要的名称,但为了我们的目的,让我们根据 ruby 命名约定将其称为 locker_app。
require './locker'
require './bag'
BAG_LIMIT = 1000
lockers = []
for i in 0..BAG_LIMIT do
lockers[i] = Locker.new(i, :small)
lockers[i+BAG_LIMIT] = Locker.new(i+BAG_LIMIT, :medium)
lockers[i+2*BAG_LIMIT] = Locker.new(i+2*BAG_LIMIT, :large)
end
while true do
puts "please enter bag size"
type = gets.strip!.to_sym
bag = Bag.new(type)
start = 0
begin
case type
when :small
when :medium
start = BAG_LIMIT
when :large
start = 2*BAG_LIMIT
else
raise ArgumentError, "please select a proper size"
end
for i in start..lockers.size-1
locker = lockers[i]
if locker.free? && locker.can_place(bag)
locker.bag = bag
puts i
break
end
puts "Sorry, no available lockers" if locker == lockers.last
end
rescue ArgumentError => e
puts e.message
end
end
这个简单的程序在无限循环 (while true) 中运行,并通过 Kernel.gets 方法在每次迭代中等待用户输入。然后,用户可以输入袋子类型(小、中或大),程序将输出储物柜的号码。
储物柜在程序开始时按顺序创建,小储物柜的索引从 0 到 999,中储物柜从 1000 到 1999,大储物柜从 2000 到 2999。然后根据袋子的类型将袋子放入储物柜.
您可以在自己的控制台中运行它,通过运行ruby locker_app.rb 来验证它是否有效。代码也可以查看here。
这是一个幼稚的实现,应该作为一个起点。你可以从这里有几个不同的方向(例如用1-index而不是像我的例子中那样用0-indexed给储物柜编号,或者维护一个当前存储了多少行李的列表,等等.
这种设计背后的总体思路是让类描述问题中的对象,然后在这些对象之间建立粘合(在本例中,locker_app 就是粘合)。我坚信首先要创造出行之有效的东西,然后逐步改进它。
如果您有任何问题,请随时提出。