Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Паттерны проектирования 2

Vitaly Shlyaga
November 09, 2012

Паттерны проектирования 2

Паттерны Наблюдатель и Компоновщик.

Vitaly Shlyaga

November 09, 2012
Tweet

More Decks by Vitaly Shlyaga

Other Decks in Education

Transcript

  1. Наблюдатель Паттерн поведения классов, определяющий зависимость типа «один ко многим»

    между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии.
  2. Наблюдатель class Employee attr_reader :name attr_accessor :title, :salary def initialize(name,

    title, salary) @name = name @title = title @salary = salary end end class Payroll def update(changed_employee) puts("#{changed_employee.name} получил повышение зарплаты!") puts("Его зарплата теперь составляет #{changed_employee.salary}!") end end ivan = Employee.new("Иван Иванов", "Оператор крана", 30000.0) # Повысить Ивану зарплату. ivan.salary=35000.0
  3. Наблюдатель class Employee attr_reader :name, :title attr_reader :salary def initialize(

    name, title, salary, payroll) @name = name @title = title @salary = salary @payroll = payroll end def salary=(new_salary) @salary = new_salary @payroll.update(self) end end
  4. Наблюдатель def initialize( name, title, salary ) @name = name

    @title = title @salary = salary @observers = [] end def salary=(new_salary) @salary = new_salary notify_observers end def notify_observers @observers.each do |observer| observer.update(self) end end
  5. Наблюдатель class TaxMan def update(changed_employee) puts("#{changed_employee.name} платит другую сумму налога!")

    end end ivan = Employee.new('Иван Иванов', 'Оператор крана', 30000.0) payroll = Payroll.new ivan.add_observer(payroll) tax_man = TaxMan.new ivan.add_observer(tax_man) ivan.salary=35000.0
  6. Наблюдатель-2 class Subject 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.update(self) end end end
  7. Наблюдатель-2 class Employee < Subject attr_reader :name, :address attr_reader :salary

    def initialize( name, title, salary) super() @name = name @title = title @salary = salary end def salary=(new_salary) @salary = new_salary notify_observers end end
  8. Наблюдатель-2 module Subject 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.update(self) end end end
  9. Наблюдатель-2 class Employee include Subject attr_reader :name, :address attr_reader :salary

    def initialize( name, title, salary) super() @name = name @title = title @salary = salary end def salary=(new_salary) @salary = new_salary notify_observers end end
  10. Наблюдатель-3 require 'observer' class Employee include Observable attr_reader :name, :address

    attr_reader :salary def initialize( name, title, salary) @name = name @title = title @salary = salary end def salary=(new_salary) @salary = new_salary changed notify_observers(self) end end
  11. Наблюдатель Позволяет создавать объекты, которые могут узнавать о поведении других

    объектов, не создавая при этом мешанину из кода, организующего взаимосвязь между ними. Большинство кода реализуется на стороне «наблюдаемого» объекта. Интерфейс между наблюдателем и наблюдаемым объектом может быть любой сложности, но если наблюдатели достаточно просты их легко можно реализовать в Ruby-style с помощью блоков.
  12. Компоновщик Структурный паттерн проектирования, объединяющий объекты в древовидную структуру для

    представления иерархии от частного к целому. Позволяет клиентам одинаково обращаться к отдельным объектам и к группам объектов.
  13. Компоновщик Manufacture Cake Make Cake Package Cake Make Batter Fill

    Pan Bake Frost Box Label AddDryIngridients AddLiquids Mix
  14. Компоновщик Manufacture Cake Make Cake Package Cake Make Batter Fill

    Pan Bake Frost Box Label AddDryIngridients AddLiquids Mix 1) Component 2) Leaf 3) Composite
  15. Компоновщик class AddDryIngredientsTask < Task def initialize super('Добавить ингридиенты.') end

    def get_time_required 1.0 # 1 минута на добавление муки и сахара. end end class MixTask < Task def initialize super('Замесить.') end def get_time_required 3.0 # Замешивать 3 минуты. end end
  16. Компоновщик class MakeBatterTask < Task def initialize super('Сделать тесто.') @sub_tasks

    = [] add_sub_task( AddDryIngredientsTask.new ) add_sub_task( AddLiquidsTask.new ) add_sub_task( MixTask.new ) end def add_sub_task(task) @sub_tasks << task end def remove_sub_task(task) @sub_tasks.delete(task) end def get_time_required @sub_tasks.inject(0.0) do |res, task| res += task.get_time_required res end end end
  17. Компоновщик class CompositeTask < Task def initialize(name) super(name) @sub_tasks =

    [] end def add_sub_task(task) @sub_tasks << task end def remove_sub_task(task) @sub_tasks.delete(task) end def get_time_required @sub_tasks.inject(0.0) do |res, task| res += task.get_time_required res end end end
  18. Компоновщик class MakeBatterTask < CompositeTask def initialize super('Сделать тесто.') add_sub_task(

    AddDryIngredientsTask.new ) add_sub_task( AddLiquidsTask.new ) add_sub_task( MixTask.new ) end end
  19. Компоновщик-2 def <<(task) @sub_tasks << task end def [](index) @sub_tasks[index]

    end def []=(index, new_value) @sub_tasks[index] = new_value end # ============================= composite = CompositeTask.new('example') composite << MixTask.new puts(composite[0].get_time_required) composite[1] = AddDryIngredientsTask.new
  20. Компоновщик Несмотря на свой рекурсивный вид, довольно простой паттерн. Позволяет

    создавать деревья объектов неограниченной глубины, в которых можно работать как с отдельными объектами, так и с их совокупностями. Довольно часто используется в библиотеках построения графических интерфейсов.
  21. Задача 1 Реализовать класс MyArray, в котором хранится некоторый массив.

    В классе реализовать метод def push(int), который добавляет целое число к массиву внутри объекта MyArray. С помощью паттерна Observer создать 3 наблюдателя, которые получают информацию о том, что состав массива внутри MyArray обновился и соответственно пересчитывают и сохраняют внутри себя обновлённую информацию о сумме элементов массива, произведении элементов массива и их среднем арифметическом.
  22. Задача 2 Входные данные — массив, содержащий различные числа и

    слова. В качестве атомарных задач реализовать несколько «фильтров»: выборка всех числовых элементов массива; выборка всех строковых элементов массива; возведение всех численных элементов массива в квадрат; «разворот» всех строковых элементов массива задом наперёд. Используя паттерн Composite, реализовать систему, позволяющую конструировать из базовых фильтров различные составные, сложные фильтры, объединяющие базовые фильтры в различных комбинациях. Реализовать возможность конструирования фильтров, используя синтаксис массивов (<<, [], []=).