Patrón Singleton
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 42 de 57.
Un patrón de diseño es una solución comprobada para un problema de diseño común. El patrón singleton garantiza que una clase tenga exactamente una instancia, accesible desde cualquier lugar. La biblioteca estándar de Ruby lo incluye: require 'singleton' y include Singleton añaden un método de clase 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)Salida:
dark
trueinclude Singleton también hace que new sea privado, por lo que no se puede crear una segunda instancia. Cada parte del programa que solicita instance obtiene el mismo objeto:
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
endSalida:
3
private method `new' called for class CounterLa misma idea escrita manualmente es un método de clase que crea la instancia en el primer uso y un new privado. Esto muestra lo que el módulo hace por ti:
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.levelSalida:
3Usa los singleton con moderación. Un singleton es un estado global: cualquier código puede cambiarlo, y las pruebas no pueden comenzar a partir de una copia limpia. Son adecuados para cosas que realmente existen una sola vez por programa, como un registrador o la configuración; a menudo es más claro pasar un objeto como parámetro:
# más fácil de probar: el logger se pasa
def process(order, log)
log.write("processing #{order.id}")
endDesafío
FácilCompleta el singleton AppLogger con include Singleton. Mantiene un array de entradas y tiene log(message, level), que almacena [INFO] message o [ERROR] message (el nivel en mayúsculas), entries y error_count. Los helpers handle_info(message) y handle_error(message) en functions.rb registran ambos mediante AppLogger.instance, por lo que llegan al mismo objeto.
El código proporcionado lee líneas info,message o error,message, las envía mediante los helpers, imprime cada entrada y errors: 1, y comprueba que AppLogger.new sea rechazado.
Tu código va en app_logger.rb y functions.rb. main.rb contiene el código de entrada/salida proporcionado y no se puede editar.
Pruébalo tú mismo
require_relative 'app_logger'
require_relative 'functions'
# Código de entrada/salida suministrado: déjalo tal como está
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
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesVariables de instanciaMétodos y selfto_s e inspectRepaso: tarjeta de biblioteca4Encapsulación
Métodos privadosMétodos protegidosAsignadores privadosProtección del estadoRepaso: máquina expendedora7Polimorfismo y tipado pato
PolimorfismoTipado patoMétodos abstractoscase y clasesRepaso: métodos de pago2Accesores y self
Lectores y escritoresSetters personalizadosself en los métodosIdentidad e igualdadRepaso: lista de contactos5Herencia
SubclasesSobrescritura de métodosLlamar a superis_a? y ancestrosRepaso - Nómina del personal8Métodos especiales
Igualdad y hashMétodos de operadoresIndexación y adiciónColecciones personalizadasRepaso: fracciones11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de Ruby online