**Draft
Varying the Algorithm with the Template Method Варирование алгоритма с помощью Шаблонного Метода
class Users::Physic < Users::Base def initialize name, website @name = name @website = website end def description puts("#{@name} [#{@website}] (#{class.to_s})") end end class Users::Juristic < Users::Base def initialize name, company @name = name @company = company end def description puts("#{@name} [#{@company}] (#{class.to_s})") end end
class Users::Base def description puts("#{printable_name} (#{class.to_s})") end def printable_name 'abstract name' end end class Users::Physic < Users::Base def initialize name, website @name = name @website = website end def printable_name "#{@name} [#{@website}]" end end class Users::Juristic < Users::Base def initialize name, company @name = name @company = company end def printable_name "#{@name} [#{@company}]" end end
> physic = Users::Physic.new('Google', 'http://google.com') > physic.description > 'Google [http://google.com] (Users::Physic)' => juristic = Users::Juristic.new('Yandex', 'Yandex Inc') => juristic.description > 'Yandex [Yandex Inc] (Users::Juristic)' => abstract_user = Users::Base.new => abstract_user.description > 'abstract name (Users::Base)'
Replacing the Algorithm with the Strategy Замена Алгоритма с помощью Стратегии
class Users::Base def description 'It's a description of Users::Base' end end class PlainTextFormatter def report text puts '<plain text>' puts text puts '<plain text>' end end class HTMLFormatter def report text puts '<html>' puts '<head>' puts '</head>' puts '<body>' puts text puts '</body>' puts '</html>' end end
class Users::Base def initialize name, formatter @name = name @formatter = formatter end def report fomatter.report(self) end end class PlainTextFormatter def report context puts '<plain text>' puts context.name puts '<plain text>' end end class HTMLFormatter def report context puts '<html>' puts '<head>' puts '</head>' puts '<body>' puts context.name puts '</body>' puts '</html>' end end
> user = Users::Base.new('username', HTMLFormatter.new) > user.report > user = Users::Base.new('username', PlainTextFormatter.new) > user.report
class Users::Base def initialize name, &formatter @name = name @formatter = formatter end def report formatter.call self end end
> PLAIN_TEXT_FORMATTER = lambda do |context| > puts '<plain text>' > puts context.name > puts '<plain text>' > end > HTML_FORMATTER = lambda do |context| > puts '<html>' > puts '<head>' > puts '</head>' > puts '<body>' > puts context.name > puts '</body>' > puts '</html>' > end > user = Users::Base.new('username', PLAIN_TEXT_FORMATTER) > user.report > user = Users::Base.new('username', HTML_FORMATTER) > user.report
Keeping Up with the Times with the Observer
class Users::Base attr_reader :payment def initialize name, payment, payment_notification @name = name @payment = payment @payment_notification = payment_notification end def payment= new_payment @payment = new_payment payment_notification.update(self) end end class PaymentNotification def update puts "#{self.name} payment updated to #{self.payment}" end end
module Observers def initialize @observers=[] end def add_observer &observer @observers << observer end def delete_observer observer @observers.delete(observer) end def notify_observers @observers.each do |observer| observer.call(self) end end end class Users::Base include Observers attr_reader :payment def initialize name, payment super() @name = name @payment = payment end def payment= new_payment @payment = new_payment notify_observers end end
> user = Users::Base.new('username', 35000) > user.add_observer do |changed_user| > puts "#{changed_user.name} payment updated to #{changed_user.payment}" > end > user.payment = 40000 => 'username payment updated to 40000'
class Users::Base < ActiveRecord attr_accessor :payment def initialize name, payment super() @name = name @payment = payment end def payment= new_payment @payment = new_payment notify_observers end end class NotificationObserver < ActiveRecord::Observer observe Users::Base def after_update(user) puts "#{user.name} updated" end end
> user = Users::Base.new('username', 30000) > user.payment = 45000 => 'username updated'
Assembling the Whole from the Parts with the Composite
class Users::Base < ActiveRecord attr_reader :payment def initialize name, payment super() @name = name @payment = payment @children = [] end def add child @children << child end def children @children end end > user_one = Users::Base.new('username', 30000) > user_one.add Users::Base.new('username', 40000) > user_one.add Users::Base.new('username',50000) > user_one.children[0].add Users::Base.new('username', 60000) > > payment_sum = user_one.payment + user_one.children[0].payment > + user_one.children[1].payment + user_one.children[0].children[0].payment class UsersComposite < User def payment_sum payment_sum = 0.0 @children.each{|child| time += child.payment} payment_sum end def << child add child end def [] index @children[index] end def []= index, new_child @children[index] = new_child end > composite = UsersComposite.new > composite << user_one > payment_sum = composite.payment_sum
Reaching into a Collection with the Iterator
class ExternalArrayIterator def initialize(array) @array = array @index = 0 end def has_next? @index < @array.length end def next_item value = @array[@index] @index += 1 value end end >> array = [1,'aaa', Users::Base.new] >> iterator = ExtrenalArrayIterator.new(array) >> while iterator.has_next? >> iterator.next_item.to_s >> end class ArrayIterator < Enumerable end class InternalArrayIterator def self.for_each_element(array) i = 0 while i < array.length yield(array[i]) i += 1 end end end >> array = [1, 'aaa', Users::Base.new] >> InternalArrayIterator.for_each_element(array){|element| element.to_s}
Getting Things Done with Commands
class Users::Administrator < Users::Base def on_action #Maybe get list of all users end end class Users::Support < Users::Base def on_action #Maybe get list of all users except administrators end end class Users::Base attr_accessor :command def initialize command @command = command end def on_action @command.execute if @command end end class UsersListCommand def execute end end class UserListExceptAdminsCommand def execute end end > Users::Administrator.new(UsersListCommand.new) > Users::Support.new(UserListExceptAdminsCommand.new) class Users::Base attr_accessor :command def initialize &block @command = block end def on_action @command.call if @command end end > Users::Base.new do > > end