Wzorzec Singleton
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 42 z 57.
Wzorzec projektowy to sprawdzone rozwiązanie typowego problemu projektowego. Wzorzec singleton gwarantuje, że klasa ma dokładnie jedną instancję, dostępną z każdego miejsca. Biblioteka standardowa Ruby ma go wbudowanego: require 'singleton' i include Singleton dodają metodę klasową instance:
require 'singleton'
class Settings
include Singleton
attr_accessor :theme
def initialize
@theme = "light"
end
end
Settings.instance.theme = "dark"
puts Settings.instance.theme
puts Settings.instance.equal?(Settings.instance)Wynik:
dark
trueinclude Singleton sprawia również, że new jest prywatne, więc nie można utworzyć drugiej instancji. Każda część programu, która wywołuje instance, otrzymuje ten sam obiekt:
require 'singleton'
class Counter
include Singleton
attr_reader :hits
def initialize
@hits = 0
end
def hit
@hits += 1
end
end
def page_a
Counter.instance.hit
end
def page_b
2.times { Counter.instance.hit }
end
page_a
page_b
puts Counter.instance.hits
begin
Counter.new
rescue NoMethodError => e
puts e.message
endWynik:
3
private method `new' called for class CounterTa sama idea zapisana ręcznie to metoda klasy, która tworzy instancję przy pierwszym użyciu, oraz prywatna metoda new. Pokazuje to, co moduł robi za ciebie:
class Config
def self.instance
@instance ||= new
end
private_class_method :new
attr_accessor :level
def initialize
@level = 1
end
end
Config.instance.level = 3
puts Config.instance.levelWynik:
3Używaj singletonów oszczędnie. Singleton to stan globalny: dowolny kod może go zmienić, a testy nie mogą zaczynać od czystej kopii. Singletony sprawdzają się w przypadku rzeczy, które rzeczywiście występują tylko raz w programie, takich jak rejestrator lub konfiguracja; często jaśniejsze jest przekazanie obiektu jako parametru:
# łatwiejsze do testowania: logger jest przekazywany jako argument
def process(order, log)
log.write("processing #{order.id}")
endWyzwanie
ŁatwyUzupełnij singleton AppLogger, używając include Singleton. Przechowuje on tablicę wpisów i ma metody log(message, level), która zapisuje [INFO] message lub [ERROR] message (poziom wielkimi literami), entries oraz error_count. Metody pomocnicze handle_info(message) i handle_error(message) w functions.rb obie logują za pośrednictwem AppLogger.instance, więc korzystają z tego samego obiektu.
Dostarczony kod odczytuje wiersze info,message lub error,message, przekazuje je do metod pomocniczych, wypisuje każdy wpis i errors: 1 oraz sprawdza, czy AppLogger.new jest niedozwolone.
Twój kod umieść w plikach app_logger.rb i functions.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'app_logger'
require_relative 'functions'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input = []
while (line = gets)
input << line.chomp
end
input.each do |line|
level, message = line.split(",", 2)
level == "error" ? handle_error(message) : handle_info(message)
end
AppLogger.instance.entries.each { |e| puts e }
puts "errors: #{AppLogger.instance.error_count}"
begin
AppLogger.new
puts "new is allowed"
rescue NoMethodError
puts "new is private"
end
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasZmienne instancjiMetody i selfto_s i inspectPowtórzenie – karta biblioteczna4Hermetyzacja
Metody prywatneMetody chronionePrywatne setteryOchrona stanuPowtórzenie – automat vendingowy7Polimorfizm i typowanie kacze
PolimorfizmTypowanie kaczeMetody abstrakcyjnecase i klasyPowtórzenie – metody płatności10Wzorce projektowe, część 2
Delegowanie z ForwardableWzorzec dekoratoraWzorzec budowniczegoWzorzec stanu2Metody dostępowe i self
Gettery i setteryWłasne setteryself w metodachTożsamość i równośćPowtórzenie – lista kontaktów5Dziedziczenie
PodklasyNadpisywanie metodWywoływanie superis_a? i przodkowiePowtórka – lista płac pracowników8Metody specjalne
Równość i hashMetody operatorówIndeksowanie i dodawanieWłasne kolekcjePowtórka – ułamki11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Kompilator Ruby online