Patron Singleton
Fait partie de la section Programmation orientée objet du Journey Ruby de Coddy. Leçon 42 sur 57.
Un motif de conception est une solution éprouvée à un problème de conception courant. Le motif singleton garantit qu’une classe possède exactement une instance, accessible depuis n’importe où. La bibliothèque standard de Ruby l’intègre : require 'singleton' et include Singleton ajoutent une méthode de classe 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)Sortie :
dark
trueinclude Singleton rend également new privé, de sorte qu’aucune seconde instance ne puisse être créée. Chaque partie du programme qui demande instance obtient le même objet :
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
endSortie :
3
private method `new' called for class CounterLa même idée écrite à la main consiste en une méthode de classe qui crée l’instance lors de la première utilisation et en un new privé. Cela montre ce que le module fait pour vous :
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.levelSortie :
3Utilisez les singletons avec parcimonie. Un singleton est un état global : n’importe quel code peut le modifier, et les tests ne peuvent pas commencer avec une copie vierge. Ils conviennent aux éléments qui n’existent réellement qu’une seule fois par programme, comme un logger ou la configuration ; passer un objet en paramètre est souvent plus clair :
# plus facile à tester : le logger est passé en paramètre
def process(order, log)
log.write("processing #{order.id}")
endDéfi
FacileComplétez le singleton AppLogger avec include Singleton. Il conserve un tableau d’entrées et possède log(message, level), qui stocke [INFO] message ou [ERROR] message (le niveau en majuscules), ainsi que entries et error_count. Les fonctions auxiliaires handle_info(message) et handle_error(message) dans functions.rb journalisent toutes deux via AppLogger.instance ; elles atteignent donc le même objet.
Le code fourni lit les lignes info,message ou error,message, les transmet aux fonctions auxiliaires, affiche chaque entrée ainsi que errors: 1, et vérifie que AppLogger.new est refusé.
Votre code doit être placé dans app_logger.rb et functions.rb. main.rb contient le code d’entrée/sortie fourni et ne peut pas être modifié.
Essayez vous-même
require_relative 'app_logger'
require_relative 'functions'
# Code d'entrée/sortie fourni : le garder tel quel
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
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Classes et objets
Travailler avec des fichiersDéfinir des classesVariables d’instanceMéthodes et selfto_s et inspectRécapitulatif - Carte de bibliothèque4Encapsulation
Méthodes privéesMéthodes protégéesSetters privésProtéger l’étatRécapitulatif - Distributeur automatique7Polymorphisme et typage canard
PolymorphismeTypage canardMéthodes abstraitesCas et classesRécapitulatif - méthodes de paiement10Patrons de conception – Partie 2
Délégation avec ForwardablePatron DécorateurPatron BuilderPatron État2Accesseurs et self
Lecteurs et écrivainsSetters personnalisésself dans les méthodesIdentité et égalitéRécapitulatif - Liste de contacts5Héritage
Sous-classesRedéfinition des méthodesAppeler superis_a? et ancêtresRécapitulatif - Paie du personnel8Méthodes spéciales
Égalité et hachageMéthodes d’opérateursIndexation et ajoutCollections personnaliséesRécapitulatif - Fractions11Projet : Gestion de bibliothèque
Livres et membresEmprunter des livresEntraînez-vous par vous-même : Compilateur Ruby en ligne