O slideshow foi denunciado.

Ruby - Design patterns tdc2011

3.121 visualizações

Publicada em

Apresentação Sobre Design Patterns na trilha de Ruby/Python do TDC 2011 Floripa

Publicada em: Tecnologia, Educação

Ruby - Design patterns tdc2011

  1. 1. Design Patterns + Ruby
  2. 2. @rs_felix http://github.com/fellix http://www.crafters.com.br @crafterstudiohttp://blog.rollingwithcode.com
  3. 3. Por que Ruby?
  4. 4. 1995
  5. 5. Erich Gamma, Richard Helm,Raph Johnson, John Vlissides
  6. 6. “Gang of Four”
  7. 7. Design Patterns
  8. 8. Template Method
  9. 9. class Relatorio def generate output_head output_body output_footer end def output_head end def output_body end def output_footer endend
  10. 10. class Relatorio def generate output_head output_body output_footer end def output_head end def output_body end def output_footer endend
  11. 11. class Relatorio def generate output_head Template output_body Method output_footer end def output_head end def output_body end def output_footer endend
  12. 12. class HTMLRelatorio < Relatorio def output_head puts "<html><head> <title>Relatório HTML</title> </head>" end def output_body puts "<body>...</body>" end def output_footer puts "</html>" endend
  13. 13. class HTMLRelatorio < Relatorio def output_head puts "<html><head> <title>Relatório HTML</title> </head>" end def output_body puts "<body>...</body>" end def output_footer puts "</html>" endend
  14. 14. class HTMLRelatorio < Relatorio def output_head puts "<html><head> <title>Relatório HTML</title> </head>" end def output_body puts "<body>...</body>" end def output_footer puts "</html>" endend
  15. 15. relatorio = HTMLRelatorio.newrelatorio.generate
  16. 16. relatorio = HTMLRelatorio.newrelatorio.generate
  17. 17. class Relatorio def generaterelatorio = HTMLRelatorio.new output_headrelatorio.generate output_body output_footer end end
  18. 18. <html> <head><title>...</title></head> relatorio = HTMLRelatorio.new <body> relatorio.generate ... </body></html>
  19. 19. Strategy
  20. 20. Delegar ao invés de herdar
  21. 21. class Formatter def format(text) endend
  22. 22. class Formatter def format(text) raise "Abstract method" endend
  23. 23. class HTMLFormatter < Formatter def format(text) puts "<html> " puts "<head> " puts "<title>...</title></head> " puts "<body>#{text}</body></html>" endend
  24. 24. class HTMLFormatter < Formatter def format(text) puts "<html> " puts "<head> " puts "<title>...</title></head> " puts "<body>#{text}</body></html>" endend
  25. 25. class HTMLFormatter def format(text) puts "<html> " puts "<head> " puts "<title>...</title></head> " puts "<body>#{text}</body></html>" endend
  26. 26. Duck Typingclass HTMLFormatter def format(text) puts "<html> " puts "<head> " puts "<title>...</title></head> " puts "<body>#{text}</body></html>" endend
  27. 27. class Relatorio def initialize(formatter) @formatter = formatter end def generate(text) @formatter.format(text) endend
  28. 28. class Relatorio def initialize(formatter) @formatter = formatter end def generate(text) @formatter.format(text) endend
  29. 29. class Relatorio def initialize(formatter) @formatter = formatter end def generate(text) @formatter.format(text) endend
  30. 30. class Relatorio def initialize(formatter) @formatter = formatter Delegate end def generate(text) @formatter.format(text) endend
  31. 31. relatorio = Relatorio.new(HTMLFormatter.new)relatorio.generate("Muitas e muitas coisas")
  32. 32. relatorio = Relatorio.new(HTMLFormatter.new)relatorio.generate("Muitas e muitas coisas")
  33. 33. relatorio = Relatorio.new(HTMLFormatter.new)relatorio.generate("Muitas e muitas coisas")
  34. 34. Observer
  35. 35. Manter-se informado sobre determinadas mudanças em objetos
  36. 36. class NotaFiscal def pagar ... endend
  37. 37. class FluxoCaixa def atualizar ... endend
  38. 38. Consulta no bancoclass FluxoCaixa de dados todas as def atualizar notas pagas e ... atualiza o fluxo de end caixaend
  39. 39. pagarNotaFiscal FluxoCaixa
  40. 40. class NotaFiscal def pagar ... endend
  41. 41. class NotaFiscal def pagar (fluxo) ... fluxo.atualizar endend
  42. 42. class NotaFiscal def initialize (...) ... @observers = [] end def pagar ... endend
  43. 43. class NotaFiscal def add_observer (observer) @observers << observer end def notify_observers @observers.each do |o| o.update(self) end endend
  44. 44. class FluxoCaixa def atualizar ... end def update (nota_fiscal) ... endend
  45. 45. fluxo_caixa = FluxoCaixa.newnota_fiscal = NotaFiscal.newnota_fiscal.add_observer fluxo_caixanota_fiscal.pagar
  46. 46. require "observer"class NotaFiscal include Observable def pagar ... changed notify_observers(self) endend
  47. 47. require "observer"class NotaFiscal include Observable def pagar ... changed notify_observers(self) endend
  48. 48. require "observer"class NotaFiscal include Observable def pagar ... changed notify_observers(self) endend
  49. 49. require "observer"class NotaFiscal include Observable def pagar ... changed notify_observers(self) endend
  50. 50. require "observer"class NotaFiscal include Observable def pagar @changed = true ... changed notify_observers(self) endend
  51. 51. require "observer" class NotaFiscal include Observable@observers.each { pagar def |o| o.update(object) } if @changed ... changed notify_observers(self) end end
  52. 52. class FluxoCaixa def atualizar ... end def update (nota_fiscal) ... endend
  53. 53. fluxo_caixa = FluxoCaixa.newnota_fiscal = NotaFiscal.newnota_fiscal.add_observer fluxo_caixanota_fiscal.pagar
  54. 54. notificanota_fiscal fluxo_caixa = FluxoCaixa.new fluxo_caixa nota_fiscal = NotaFiscal.new nota_fiscal.add_observer fluxo_caixa nota_fiscal.pagar
  55. 55. Factory
  56. 56. Fornecer uma interface para a criação de objetos, sem especificar a classe concreta
  57. 57. HTMLReader.new
  58. 58. PDFReader.new
  59. 59. class ReaderFactory def initialize (format) @reader_class = self.class.const_get("#{format}Reader") end def reader @reader_class.new endend
  60. 60. class ReaderFactory def initialize (format) @reader_class = self.class.const_get("#{format}Reader") end def reader @reader_class.new endend
  61. 61. class ReaderFactory def initialize (format) @reader_class = self.class.const_get("#{format}Reader") end def reader @reader_class.new endend
  62. 62. class ReaderFactory def initialize (format) @reader_class = self.class.const_get("#{format}Reader") end def reader @reader_class.new endend
  63. 63. html_reader = ReaderFactory.new("HTML").reader
  64. 64. pdf_reader = ReaderFactory.new("PDF").reader
  65. 65. class ReaderFactory def self.pdf_reader ReaderFactory.new("PDF").reader end def self.html_reader ReaderFactory.new("HTML").reader endend
  66. 66. html_reader = ReaderFactory.html_reader
  67. 67. Active Record Factory
  68. 68. class Base ...end
  69. 69. class Base def self.mysql_connection ... endend
  70. 70. class Base def self.postgresql_connection ... endend
  71. 71. adapter = "mysql"method_name = "#{adapter}_connection"Base.send(method_name, config)
  72. 72. Builder
  73. 73. Criar objetos complexos de forma legível, passo a passo
  74. 74. class Pizza attr_accessor :massa, :molho, :coberturaend
  75. 75. class PizzaBuilder attr_reader :pizza def initialize @pizza = Pizza.new endend
  76. 76. class CalabresaBuilder < PizzaBuilder def molho @pizza.molho = "Tomate" end def massa @pizza.massa = "Pão" end def cobertura @pizza.cobertura = "queijo, calabresa" endend
  77. 77. builder = CalabresaBuilder.newbuilder.molhobuilder.coberturabuilder.massapizza = builder.pizza
  78. 78. pizza = CalabresaBuilder.new .molho .cobertura .massa .pizza
  79. 79. class CalabresaBuilder < PizzaBuilder def molho @pizza.molho = "Tomate" self end def massa @pizza.massa = "Pão" self end def cobertura @pizza.cobertura = "queijo, calabresa" self endend
  80. 80. builder = CalabresaBuilder.newbuilder.molho_and_coberturapizza = builder.pizza
  81. 81. class PizzaBuilder def method_missing(name, *args) methods = name.to_s.split("_") return super(name, *args) unless methods[1] == "and" methods.each do |method| next if method == "and" send(method) end endend
  82. 82. builder.molho_and_cobertura
  83. 83. builder.massa_and_cobertura
  84. 84. builder.molho_and_cobertura_and_massa
  85. 85. Adapter
  86. 86. Conectar objetos que não tem uma interface comum
  87. 87. class Padrao1 def conectar (cabo) cabo.energizar endend
  88. 88. class Padrao1 def conectar (cabo) cabo.energizar endend
  89. 89. class CaboPadrao1 def energizar ... endend
  90. 90. class Padrao2 def conectar (cabo) cabo.executar endend
  91. 91. class Padrao2 def conectar (cabo) cabo.executar endend
  92. 92. class CaboPadrao2 def executar ... endend
  93. 93. class CaboPadrao2 def executar ... endend
  94. 94. class CaboPadrao2 def executar tomada = Padrao2.new ... tomada.conectar end CaboPadrao2.newend
  95. 95. class CaboPadrao2 def executar tomada = Padrao1.new ... tomada.conectar end CaboPadrao2.newend
  96. 96. class CaboPadrao2 def executar tomada = Padrao1.new ... tomada.conectar end CaboPadrao2.newend
  97. 97. class AdapterPadrao2 def initialize(cabo_padrao2) @cabo = cabo_padrao2 end def energizar @cabo.executar endend
  98. 98. class AdapterPadrao2 def initialize(cabo_padrao2) @cabo = cabo_padrao2 end def energizar @cabo.executar endend
  99. 99. class AdapterPadrao2 def initialize(cabo_padrao2) @cabo = cabo_padrao2 end def energizar @cabo.executar endend
  100. 100. adapter = AdapterPadrao2.new(CaboPadrao2.new)tomada = Padrao1.newtomada.conectar(adapter)
  101. 101. adapter = AdapterPadrao2.new(CaboPadrao2.new)tomada = Padrao1.newtomada.conectar(adapter)
  102. 102. tomada adapter caboadapter = AdapterPadrao2.new(CaboPadrao2.new)tomada = Padrao1.newtomada.conectar(adapter)
  103. 103. Proxy
  104. 104. class ContaBancaria def initialize(saldo) @saldo = saldo end def depositar!(valor) @saldo += valor end def sacar!(valor) @saldo -= valor end def some_method endend
  105. 105. class ContaBancariaProxy def initialize(conta_bancaria) @conta_bancaria = conta_bancaria end def depositar!(valor) @conta_bancaria.depositar! valor end def sacar!(valor) @conta_bancaria .sacar! valor endend
  106. 106. Protection Proxy
  107. 107. class ContaBancariaProxy def initialize(conta_bancaria) @conta_bancaria = conta_bancaria end def depositar!(valor) @conta_bancaria.depositar! valor end def sacar!(valor) @conta_bancaria .sacar! valor endend
  108. 108. class ContaBancariaProxy def initialize(conta_bancaria, owner) @conta_bancaria = conta_bancaria @owner = owner end protected def check_access raise "Illegal Access" unless User. login == @owner endend
  109. 109. class ContaBancariaProxy def depositar!(valor) check_access @conta_bancaria.depositar! valor end def sacar!(valor) check_access @conta_bancaria .sacar! valor endend
  110. 110. Decorator
  111. 111. class Coffee def price @price end def ingredients @ingredients endend
  112. 112. class MilkDecorator def initialize (coffee) @coffee = coffee end def price coffee.price + 0.5 end def ingredients coffee.ingredients + ", Leite" endend
  113. 113. class MilkDecorator def initialize (coffee) @coffee = coffee end def price coffee.price + 0.5 end def ingredients coffee.ingredients + ", Leite" endend
  114. 114. class MilkDecorator def initialize (coffee) @coffee = coffee end def price coffee.price + 0.5 end def ingredients coffee.ingredients + ", Leite" endend
  115. 115. class MilkDecorator def initialize (coffee) @coffee = coffee end def price coffee.price + 0.5 end def ingredients coffee.ingredients + ", Leite" endend
  116. 116. coffee = Coffee.new(1.5, "Café, Água")puts coffee.ingredients
  117. 117. coffee = Coffee.new(1.5, "Café, Água")puts coffee.ingredients Café, Água
  118. 118. coffee = Coffee.new(1.5, "Café, Água")coffee = MilkDecorator.new coffeeputs coffee.ingredientsputs coffee.price
  119. 119. coffee = Coffee.new(1.5, "Café, Água")coffee = MilkDecorator.new coffeeputs coffee.ingredients Café, Água, Leiteputs coffee.price
  120. 120. coffee = Coffee.new(1.5, "Café, Água")coffee = MilkDecorator.new coffeeputs coffee.ingredientsputs coffee.price 2.0
  121. 121. class ChocolateDecorator def initialize (coffee) @coffee = coffee end def price coffee.price + 1.0 end def ingredients coffee.ingredients + ", Chocolate" endend
  122. 122. coffee = Coffee.new(1.5, "Café, Água")coffee = ChocolateDecorator.new coffeeputs coffee.ingredients
  123. 123. coffee = Coffee.new(1.5, "Café, Água")coffee = ChocolateDecorator.new coffee Café, Água,puts coffee.ingredients Chocolate
  124. 124. coffee = Coffee.new(1.5, "Café, Água")coffee = ChocolateDecorator.new coffeeputs coffee.ingredients
  125. 125. coffee = Coffee.new(1.5, "Café, Água")coffee = ChocolateDecorator.new coffee
  126. 126. coffee = Coffee.new(1.5, "Café, Água")coffee = ChocolateDecorator.new coffeecoffee = MilkDecorator.new coffee
  127. 127. coffee = Coffee.new(1.5, "Café, Água")coffee = ChocolateDecorator.new coffeecoffee = MilkDecorator.new coffee Café, Água,puts coffee.ingredients Chocolate, Leite
  128. 128. Singleton
  129. 129. Garantir que só haja uma instancia de determinado objeto
  130. 130. @count
  131. 131. @count@@count
  132. 132. class CountTester @@count = 0 def initialize @count = 0 end def self.increment @@count++ end def increment @count++ endend
  133. 133. class CountTester Variável @@count = 0 Global def initialize @count = 0 end def self.increment @@count++ end def increment @count++ endend
  134. 134. class CountTester @@count = 0 def initialize Variável @count = 0 Local end def self.increment @@count++ end def increment @count++ endend
  135. 135. class CountTester @@count = 0 def initialize @count = 0 end Metódo def self.increment Estático @@count++ end def increment @count++ endend
  136. 136. class CountTester @@count = 0 def initialize @count = 0 end def self.increment @@count++ end Metódo de def increment Instância @count++ endend
  137. 137. class CountTester Variável COUNT = 0 Globalend
  138. 138. class Logger @@instance = Logger.new def self.instance @@instance endend
  139. 139. logger1 = Logger.instancelogger2 = Logger.instance
  140. 140. logger = Logger.new
  141. 141. class Logger @@instance = Logger.new def self.instance @@instance endend
  142. 142. class Logger @@instance = Logger.new def self.instance @@instance end private_class_method :newend
  143. 143. require "singleton"class Logger include Singletonend
  144. 144. logger = Logger.new
  145. 145. logger = Logger.new private method ‘new’ called for Logger::Class
  146. 146. logger = Logger.instance
  147. 147. Obrigado @rs_felix http://github.com/fellix http://www.crafters.com.br @crafterstudiohttp://blog.rollingwithcode.com

×