Фабричные методы
Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 15 из 57.
Фабричный метод — это метод класса, который создаёт и возвращает экземпляр. Он даёт имя одному из способов создания объекта. Внутри метода класса new означает self.new:
class Temperature
attr_reader :celsius
def initialize(celsius)
@celsius = celsius
end
def self.from_fahrenheit(f)
new((f - 32) * 5 / 9.0)
end
def self.freezing
new(0)
end
end
puts Temperature.from_fahrenheit(212).celsius
puts Temperature.freezing.celsiusВывод:
100.0
0Преобразование текста в объект — распространённая задача для фабрики. Логика разбора находится рядом с классом, а initialize остаётся простым:
class Duration
attr_reader :seconds
def initialize(seconds)
@seconds = seconds
end
def self.parse(text)
new(text.split(":").map(&:to_i).reduce(0) { |acc, part| acc * 60 + part })
end
end
puts Duration.parse("1:30").seconds
puts Duration.parse("2:00:05").secondsРезультат:
90
7205Фабрика может отклонить некорректные входные данные. Возврат nil позволяет вызывающему коду проверить результат с помощью if; вызов ошибки останавливает программу, если только вызывающий код не перехватит её:
class Color
attr_reader :hex
def initialize(hex)
@hex = hex
end
def self.parse(text)
return nil unless text.match?(/\A#[0-9a-f]{6}\z/i)
new(text.downcase)
end
end
["#FF8800", "orange"].each do |text|
color = Color.parse(text)
puts color ? "ok #{color.hex}" : "not a color: #{text}"
endРезультат:
ok #ff8800
not a color: orangeprivate_class_method :new делает new вызываемым только внутри класса, поэтому фабрики становятся единственным способом создать объект:
class Money
attr_reader :cents
def initialize(cents)
@cents = cents
end
private_class_method :new
def self.from_cents(cents)
new(cents)
end
end
puts Money.from_cents(250).cents
begin
Money.new(250)
rescue NoMethodError => e
puts e.message
endВывод:
250
private method `new' called for class MoneyЗадание
ЛегкоЗавершите класс Duration. initialize(seconds) сохраняет количество секунд. Фабрика Duration.parse(text) читает значения в формате m:ss или h:mm:ss, фабрика Duration.from_minutes(m) принимает целое количество минут, plus(other) возвращает новый объект Duration с суммой, а to_s возвращает значение в формате h:mm:ss с двузначными минутами и секундами.
Предоставленный код считывает длительности: строки вроде 45m обрабатываются через from_minutes, остальные — через parse. Он выводит каждую длительность и в конце total 1:47:10.
Ваш код должен находиться в duration.rb. В main.rb находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
require_relative 'duration'
# Предоставленный код ввода/вывода: оставьте его как есть
input = []
while (line = gets)
input << line.chomp
end
durations = input.map do |line|
line.end_with?("m") ? Duration.from_minutes(line.to_i) : Duration.parse(line)
end
durations.each { |d| puts d }
puts "total #{durations.reduce(Duration.new(0)) { |sum, d| sum.plus(d) }}"
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПеременные экземпляраМетоды и selfto_s и inspectПовторение — читательский билет4Инкапсуляция
Приватные методыЗащищённые методыПриватные сеттерыЗащита состоянияПовторение — торговый автомат7Полиморфизм и утиная типизация
ПолиморфизмУтиная типизацияАбстрактные методыcase и классыПовторение — способы оплаты10Шаблоны проектирования, часть 2
Делегирование с помощью ForwardableШаблон декоратораШаблон строителяШаблон состояния2Аксессоры и self
Чтение и записьПользовательские сеттерыself в методахИдентичность и равенствоПовторение — список контактов5Наследование
ПодклассыПереопределение методовВызов superis_a? и предкиПовторение — расчёт зарплаты сотрудников8Специальные методы
Равенство и хешированиеМетоды операторовИндексация и добавлениеПользовательские коллекцииПовторение — дроби11Проект: Управление библиотекой
Книги и читателиВыдача книг3Методы и переменные классов
Методы классовПеременные экземпляра классаКонстантыФабричные методыПовторение — коды купонов6Модули и примеси
Модули и includeРасширение объектовМодуль ComparableМодуль EnumerableПовторение — спортивная лига9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор Ruby