SORU
14 NİSAN 2009, Salı


Genişletilebilir bir fabrika sınıfı Nasıl?Ruby tasarım deseni:

Tamam, sürüm kontrolü, günlük dosyalarını okumak ve veri ile bir şeyler yapmak Ruby program var sanırım. (Bilmiyorum ama durum paraleldir ve bu analojiler ile eğleniyorum). Hadi Çarşı ve Git destek istiyorum şu an sanırım. Hadi programı bir çeşit tartışma kontrol yazılımı kullanıldığını belirten yapılacağından sanırım.

Verilen bu, istediğim bir LogFileReaderFactory verilen ad bir sürüm kontrol programı dönecektir uygun bir günlük dosyası okuyucu (alt bir jenerik) okumak için günlük dosyası ve ağzından bir kurallı iç gösterimi. Yani, elbette, yapabilirim, BazaarLogFileReader ve GitLogFileReader ve sabit-kodu program, ama benim olmak istediğim kurma ve ekleme destek için yeni bir sürüm kontrol programı gibi basit plopping yeni bir sınıf dosyası dizin ile Çarşı ve Git okuyucular.

Şimdi diyebilirsin "-bir şey---log --yazılım gıt" ve "do-bir şey---log --yazılım Çarşısı" çünkü günlüğü okuyucuları için bu. Benim istediğim için mümkün olmasını eklemek için sadece bir SVNLogFileReader sınıf ve dosya aynı dizin ve otomatik olarak mümkün arayıp "bir şeyler---log yazılımı svn" olmadan HERHANGİ bir değişiklik için geri kalan program. (Dosyalar elbette belirli bir desen ile adlandırılmış ve aramayı gerektirir globbed olabilir.)

Bu Ruby yapılabilir biliyorum... ben sadece nasıl yapmam gerektiğini bilmiyorum. ya olursam eğer.

CEVAP
14 NİSAN 2009, Salı


Bir LogFileReaderFactory gerek; sadece alt sınıflar oluşturmak için nasıl LogFileReader dersi değilsiniz

class LogFileReader
  def self.create type
    case type 
    when :git
      GitLogFileReader.new
    when :bzr
      BzrLogFileReader.new
    else
      raise "Bad log file type: #{type}"
    end
  end
end

class GitLogFileReader < LogFileReader
  def display
    puts "I'm a git log file reader!"
  end
end

class BzrLogFileReader < LogFileReader
  def display
    puts "A bzr log file reader..."
  end
end

Gördüğünüz gibi, üst sınıf kendi Fabrikası gibi hareket edebilir. Şimdi, nasıl otomatik kayıt hakkında? Peki, neden bizim kayıtlı sınıflarından bir karma tutun ve her bir üye olduğunda biz onları tanımlamak yok:

class LogFileReader
  @@subclasses = { }
  def self.create type
    c = @@subclasses[type]
    if c
      c.new
    else
      raise "Bad log file type: #{type}"
    end
  end
  def self.register_reader name
    @@subclasses[name] = self
  end
end

class GitLogFileReader < LogFileReader
  def display
    puts "I'm a git log file reader!"
  end
  register_reader :git
end

class BzrLogFileReader < LogFileReader
  def display
    puts "A bzr log file reader..."
  end
  register_reader :bzr
end

LogFileReader.create(:git).display
LogFileReader.create(:bzr).display

class SvnLogFileReader < LogFileReader
  def display
    puts "Subersion reader, at your service."
  end
  register_reader :svn
end

LogFileReader.create(:svn).display

Ve sen o var. Sadece birkaç dosyaya ayırabilir ve bunları uygun şekilde gerektirir.

Eğer bu tür bir şey ilgileniyorsanız eğer Peter Norvig Design Patterns in Dynamic Languages okumalısınız. O gösterir kaç tasarım desen aslında etrafında çalışma kısıtlamaları veya yetersizlikler içinde programlama dili; ve yeterince güçlü ve esnek bir dil, değil gerçekten ihtiyacımız olan bir desen, sana sadece uygulamak ne yapmak istiyorsun. Örnekler için Dylan ve Common Lisp kullanıyor, ama onun puan çok Ruby alakalı.

Ayrıca Why's Poignant Guide to Ruby, özellikle eğer sürrealist teknik yazı ile başa çıkabilirim ama sadece 6 Bölüm 5 bakmak isteyebilirsiniz.

edit: Kapalı Jörg doğaçlama cevap; tekrarı azaltmak ve böylece her ikisi de sınıfta sürüm kontrol sistemi ve kayıt zikretmeye onu özlüyorum. Benim ikinci örnek için aşağıdaki eklenmesi oldukça basit ve anlaşılması kolay olan siz çok daha basit bir sınıfı tanımlar yazmak için izin verir.

def log_file_reader name, superclass=LogFileReader, &block
  Class.new(superclass, &block).register_reader(name)
end

log_file_reader :git do
  def display
    puts "I'm a git log file reader!"
  end
end

log_file_reader :bzr do
  def display
    puts "A bzr log file reader..."
  end
end

Üretim kodunda tabii, aslında daha iyi hata iletileri için bu sınıflar, sabit bir tanımı adı geçirilen dayalı üreterek, adlandırmak isteyebilirsiniz.

def log_file_reader name, superclass=LogFileReader, &block
  c = Class.new(superclass, &block)
  c.register_reader(name)
  Object.const_set("#{name.to_s.capitalize}LogFileReader", c)
end

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Apple&Tech Reviews & Giveaways

    Apple&Tech R

    12 Temmuz 2008
  • Plugable

    Plugable

    19 Mayıs 2010
  • Tom Megalis

    Tom Megalis

    18 NİSAN 2006