Das Factory Entwurfsmuster

Eine Fabrik produziert etwas. Und abgeleitet davon, beschreibt das Factory Entwurfsmuster, wie Objekte produziert werden.
Zunächst einmal eine beispielhafte Ausgangssituation. Eine Produktklasse deren Objekte durch einen Namen und einen Preis gekennzeichnet sind:

class Product
  attr_accessor :name, :price

  def initialize name, price
    @name = name
    @price = price
  end
end

Außerdem exestieren diverse Preisberechnungsmodelle, abgebildet durch die folgenden Klassen:

module PricingPolicy
  class Fixed
    attr_accessor :product

    def initialize product
      @product = product
    end

    def price
      product.price.to_f
    end
  end
end

Es gibt den festen Preis Fixed.

module PricingPolicy
  class Flexible < Fixed
    FACTOR = 0.8...1.5

    def price
      (super * rand(FACTOR)).round 2
    end
  end

  class Discount < Fixed
    FACTOR = 0.8

    def price
      (super * 0.8).round 2
    end
  end
end

Außerdem gibt es den flexiblen Preis (Flexible), der zufällig zwischen 80% und 150% des festen Preises schwankt. Und schließlich der Rabattpreis (Discount), der 80% des originalen Preises ausgibt.
Nun sollen die Preismodelle auf die Produkte angewendet werden. Dafür bietet sich das Factory Entwurfsmuster an, zumal damit die Verantwortung der Erstellung der Objekte zentral an einer dedizierten Stelle liegt.
In Ruby gibt es sicherlich verschiedene Ansätze, wie eine Factoy implementiert werden kann. Weit verbreitet ist folgender Ansatz:

module PricingPolicy
  POLICIES = {
    'flexible' => Flexible,
    'prestige' => Prestige
  }
  private_constant :POLICIES

  def self.for name, product=nil
    (POLICIES[name.to_s.downcase] || Fixed).new product
  end
end

Im Grunde beinhaltet die Factory einen Hash für die möglichen Objektklassen. Für den Fall, daß keine entsprechende Klasse gefunden werden kann, ist eine Standardklasse definiert (in diesem Fall Fixed).
Für die Objektgenerierende Methode wird oft for oder build verwendet, weil new suggeriert, daß ein Objekt der entsprechenden Klasse erstellt wird. In einer Factory ist das nicht der Fall. Dort werden Objekte anderer Klassen erzeugt:

book = Product.new 'Design Patterns In Ruby', 50
# => #<Product:0x000000038873d8 ... >
policy = PricingPolicy.for :discount, book
=> #<PricingPolicy::Discount:0x000000038445b0 ... >
policy.price # => 40.0
PricingPolicy.for(:flexible, book).price # => 52.02
PricingPolicy.for(:fixed, book).price # => 50.0