在Ruby中创建动态函数

时间:2018-07-26 14:20:22

标签: ruby

我正在为一副纸牌创建一个模块。我希望Deck对象能够接受下面编写的shuffle方法的另一种实现。

我本来以为我的shuffle方法应该接受一个参数,该参数是任何响应shuffle的对象。这是个好方法吗?

我不确定如何在Ruby中实现这一目标。

module PlayingCards
  class Deck
    RANKS = [*2..10, 'Jack', 'Queen', 'King', 'Ace']
    SUITS = %w{ Clubs Diamonds Hearts Spades }

    attr_accessor :cards, :discarded
    def initialize(options={})
      @cards = []
      @discarded = []
      options[:number_decks] ||= 1

      options[:number_decks].times do
        (RANKS).product(SUITS).each do |rank, suit|
          @cards << Card.new(rank, suit)
        end
      end
    end

    def shuffle()
      cards.push(*discarded).shuffle!
      discarded = []
      self
    end
  end
end

这是手牌类,负责从牌组中抽牌并折叠手牌。

module PlayingCards
  class Hand
    attr_accessor :deck, :draw_count, :cards, :discarded

    def initialize(args = {})
      @deck = args[:deck]
      @discarded = args[:deck].discarded
      @draw_count = args[:draw_count]
      @cards = []
    end

    def draw
      draw_count.times do
        cards.push(deck.cards[0])
        deck.cards.shift
      end

      cards
    end

    def fold
      discarded.push(cards).flatten!
    end
  end
end

1 个答案:

答案 0 :(得分:2)

  

我希望Deck对象能够接受下面编写的shuffle方法的另一种实现方式。

有几种方法可以实现此目的。没有一个正确的答案。这里有一些技巧:

  1. 只需定义多种方法:

    load()
  2. 定义一个高阶方法,例如:

    def shuffle
      cards.push(*discarded).shuffle!
      discarded = []
      self
    end
    
    # For example
    def shuffle_before_replacing
      cards.shuffle!
      cards.push(*discarded)
      discarded = []
      self
    end
    
  3. 注入一个依赖项来执行改组,例如:

    SHUFFLE_MODES = {
      standard: ->(cards, discarded) { cards.push(*discarded).shuffle },
      # ...
    }
    
    def shuffle(mode: :standard)
      cards = SHUFFLE_MODES.fetch(mode).call(cards, discarded)
      discarded = []
      self
    end
    

    结束

该第三种方法的主要优点是您可以独立于def shuffle(shuffler: Shuffler::Standard) shuffler = shuffler.new(cards, discarded) shuffler.shuffle cards = shuffler.cards shuffler = shuffler.discarded self end # ... module Shuffler class Base attr_reader :cards, :discarded def initialize(cards, discarded) @cards = cards @discarded = discarded end end end module Shuffler class Standard < Base def shuffle @cards.push(*discarded).shuffle @discarded = [] self end end end module Shuffler class BeforeReplacing < Base def shuffle @cards.shuffle! @cards.push(*discarded) @discarded = [] self end end end 类定义Shuffler -例如,也许最终您将拥有多种类型Deck中的每一个都可以以不同的方式使用Deck接口。 (例如,也许您想改组不同的事物,或者改组多次。)

同样,您也可以独立于ShufflerShuffler进行 test 测试。这是双向的。您现在还可以独立于Deck测试Deck(通过将模拟对象传递到Shuffler方法中)。

这项技术是这三种技术中最先进的一种,我通常只希望有经验的开发人员可以在更加复杂的场景中充分利用。鉴于我所掌握的信息有限,很难说这样的抽象在您的情况下是否仍在努力!


上面的所有代码都未经测试,因此可能找不到,但是希望这能给您一些启发。