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
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
Builder Tasarım deseni ve Fabrika Tasa...
Nasıl bir Ruby sınıfı adını alabilir m...
PHP Fabrika Tasarım Deseni nedir?...
Neden Soyut fabrika tasarım deseni iht...
C fabrika desen#: Nasıl bir nesne örne...