Design Patterns com C# Fernando Kakimoto [email_address] www.twitter.com/nandokakimoto
Quem Sou Eu? Centro de Informática - U.F.P.E.  Graduado em Ciências da Computação (2008) Mestrando em Ciências da Computação Inove Informática Engenheiro de Software / Líder de Equipe Certificações MCP | MCTS Web 2.0 SCJP 6.0 Intereseses Arquitetura, metodologias ágeis, desenvolvimento Web
Agenda Introdução Classificação Alguns padrões Princípios SOLID Anti-patterns
Introdução “ How can you distribute responsibility for design through all levels of a large hierarchy, while still maintaining consistency and harmony of overall design?”
Introdução Alexander sugeriu usar Padrões de Projeto Dicionário de termos relacionados  a decisões básicas de projeto arquitetural Cada padrão descreve um problema comum do dia a dia e sua solução A solução pode ser reusada Discussões arquiteturais passaram a ser conduzidas por essa linguagem
Introdução [GoF] Design Patterns: Elements of Reusable Object-Oriented Software
Introdução “ A design pattern names, abstracts, and identifies the key aspects of a common design structure that make it useful for creating a reusable object-oriented design .” -  Gang of Four (Gamma et al.)
Por que padrões? Procurar objetos apropriados Determinar granularidade dos objetos Estimular reuso Projetar mudanças
Nomenclatura Nome  Contrução de um vocabulário Problema Quando aplicar o padrão Solução Estrutura genérica de elementos Consequências Trade-offs da implementação
Classificação Propósito Criacional Estrutural Comportamental Escopo Classe Factory Method Adapter (class) Interpreter Template Method Objeto Abstract Factory Builder Prototype Singleton Adapter (object) Bridge Composite Decorator Facade Flyweight Proxy Chain of Responsability Command Iterator Mediator Memento Observer State Strategy Visitor
Factory Method Intenção Motivação Consequências Fornece uma interface para criação de famílias de objetos, sem especificar suas classes concretas A classe não pode antecipar o objeto que ela deve criar A classe precisa que a subclasse especifique o objeto criado Programação para interfaces Necessidade de subclasses  Creator  para criação de  Products  específicos
Factory Method Estrutura
Factory Method Exemplo
Factory Method
Factory Method public interface  Manipulator { void  DownClick(); void  Drag(); void  UpClick(); } public class  LineManipulator : Manipulator { public void  DownClick() { Console. WriteLine( "Line DownClick()" ); } public void  Drag() { Console. WriteLine( "Line Drag()" ); } public void  UpClick() { Console. WriteLine( "Line UpClick()" ); } } public class  TextManipulator : Manipulator { public void  DownClick() { Console. WriteLine( “Text DownClick()" ); } public void  Drag() { Console. WriteLine( “Text Drag()" ); } public void  UpClick() { Console. WriteLine( “Text UpClick()" ); } }
Factory Method public abstract class  Figure { public  Manipulator  Manipulator {  get; set;  } public  Figure() { CreateManipulator(); } public abstract void CreateManipulator(); public void  DoSomething() { this .Manipulator.Drag(); } } public class  LineFigure : Figure { public override void  CreateManipulator() { this. Manipulator = new   LineManipulator (); } } public class  TextFigure : Figure { public override void  CreateManipulator() { this .Manipulator = new   TextManipulator (); } }
Factory Method class  Program { static void  Main( string [ ] args) { Figure  figure =   new  LineFigure (); figure.DoSomething(); figure =  new  TextFigure (); figure.DoSomething();  } }
Decorator Intenção Motivação Consequências Adiciona responsabilidades dinamicamente a um objeto Adicionar responsabilidades a objetos ao invés de classes Responsabilidades podem ser retiradas Quando extensão por herança é impraticável Mais flexibilidade do que heranças estáticas Evita explosão de classes Inúmeros objetos semelhantes
Estrutura Decorator
Decorator Exemplo
Decorator
Decorator public abstract class  LibraryItem { public int  NumCopies {  get; set;  } public abstract void  Display(); } public class  Book : LibraryItem { private string  Author; private string  Title; public  Book( string  author , string  title , int  numCopies) { this. Author = author; this. Title = title; this. NumCopies = numCopies; } public override void  Display() { Console. WriteLine( "\n*** Book ***" ); Console. WriteLine( "Author: {0}" , Author); Console. WriteLine( "Title: {0}" , Title); Console. WriteLine( "#Copies: {0}" , NumCopies); } }
Decorator public class  Decorator : LibraryItem { protected  LibraryItem LibraryItem  {   get; set;  } public  Decorator( LibraryItem  libraryItem) { this. LibraryItem   = libraryItem; } public override void  Display() { LibraryItem.Display(); } } public abstract class  LibraryItem { public int  NumCopies {  get; set;  } public abstract void  Display(); }
Decorator class  Program { static void  Main( string [ ] args) { Book book =  new  Book( &quot;Worley&quot;, &quot;Inside ASP.NET&quot; , 10); book.Display(); Borrowable borrowBook =  new  Borrowable (book); borrowBook.BorrowItem( &quot;Customer #1&quot; ); borrowBook.BorrowItem( &quot;Customer #2&quot; ); borrowBook.Display(); } } public class  Borrowable : Decorator { public  List < string >   Borrowers {  get ;  private set ; } public  Borrowable (  LibraryItem  libraryItem ) :  base  (libraryItem) { this .Borrowers = new   List < string >(); } public void  BorrowItem( string  name) { Borrowers.Add(name); this .LibraryItem.NumCopies- -; } public override void  Display() { base. Display(); Borrowers.ForEach( b =>   Console.WriteLine ( &quot;borrower: {0}&quot; , b)); } }
Observer Intenção Motivação Consequências Define dependências entre objetos, tal que quando um objeto muda de estado, seus dependentes são notificados e atualizados Manter consistência entre objetos relacionados Manter baixo acoplamento Um objeto deve notificar outro objeto sem fazer suposições prévias Acoplamento abstrato entre Subject e Observer Suporte para comunicação broadcast Atualizações inesperadas
Observer Estrutura
Observer Exemplo
Observer
Observer public abstract class  Subject <T> { private  List < Observer <T>> Observers; public  Subject() { this .Observers = new  List < Observer <T>>(); } public void  Attach( Observer <T> o) { this .Observers.Add(o); } public void  Detach( Observer <T> o) { this .Observers.Remove(o); } public void  Notify(T data) { this .Observers.ForEach(o => o.Update(data)); } } public class  ClockTimer : Subject < DateTime > { public  DateTime  CurrentTime {  get; set;  } public  ClockTimer( DateTime  time) { this. CurrentTime = time; } public void  Tick() { this. CurrentTime =   DateTime .Now; this .Notify( this .CurrentTime); } }
Observer public interface  Observer <T> { void  Update(T data); } public class  AnalogicTimer : Observer < DateTime > { public void  Update( DateTime  time) { Console .WriteLine( &quot;AnalogicTimer {0}&quot; , time); } } public class  DigitalTimer : Observer < DateTime > { public void  Update( DateTime  time) { Console .WriteLine( &quot;DigitalTimer {0}&quot; , time); } }
Observer class  Program { static void  Main( string [ ] args) { ClockTimer  timer =   new  ClockTimer ( DateTime .Now); AnalogicTimer  analogicTimer =  new  AnalogicTimer (); timer.Attach(analogicTimer); DigitalTimer  digitalTimer =  new  DigitalTimer (); timer.Attach(digitalTimer); timer.Tick(); timer.Detach(analogicTimer); Thread .Sleep(5000); timer.Tick(); } }
Strategy Intenção Motivação Consequências Define uma família de algoritmos, encapsula cada um, e os torna substituíveis. Configurar uma classe com um entre vários comportamentos Diferentes variação para um mesmo algoritmo Encapsula detalhes de implementação de um algoritmo Define um comportamento para contextos de reuso Alternativa a extensão de classes Elimina instruções condicionais
Strategy Estrutura
Strategy Exemplo
Strategy
Strategy public interface  PersistenceStrategy <T> { void  Save(T item); void  Remove(T item); bool  Exists(T item); } public class  CollectionPersistence <T> :  PersistenceStrategy <T> { public void  Save(T item) { Console. WriteLine( &quot;CollectionPersistence: Save&quot; ); } public void  Remove(T item) { Console .WriteLine( &quot;CollectionPersistence: Remove&quot; ); } public bool  Exists(T item) { Console .WriteLine( &quot;CollectionPersistence: Exists&quot; ); return false; } }
Strategy class  Program { static void  Main( string [ ] args) { Contact  c =  new  Contact() { Name =   &quot;Fernando Kakimoto&quot;, PhoneNumer =  &quot;(81)9162-2997&quot;, Email =  &quot;nandokakimoto@gmail.com&quot; }; PersistenceStrategy < Contact > persistence =  new  CollectionPersistence < Contact >(); persistence.Save(c); persistence.Remove(c); persistence.Exists(c); persistence =  new  DataBasePersistence < Contact >(); persistence.Save(c); persistence.Remove(c); persistence.Exists(c); } } public class  DataBasePersistence <T> :  PersistenceStrategy <T> { public void  Save(T item) { Console .WriteLine( &quot;DataBasePersistence: Save&quot; ); } public void  Remove(T item) { Console .WriteLine( &quot;DataBasePersistence: Remove&quot; ); } public bool  Exists(T item) { Console .WriteLine( &quot;DataBasePersistence: Exists&quot; ); return false; } }
SOLID Principles Expõe aspectos de  gestão de dependência  no desenvolvimento orientado à objetos Identifica código frágil e difícil de mudar/estender Base para as  –ilities  desejadas por desenvolvedores Março de 1995, Robert C. Martin
SOLID Principles S ingle Responsability Principle O pen-Closed Principle L iskov Substituition Principle I nterface Segregation Principle D ependency Inversion Principle
Single Responsability Principle Uma classe deve ter uma única razão para mudar Uma responsabilidade é um eixo de mudança O que considerar como responsabilidade?
Open-Closed Principle Entidades de software devem ser abertas para extensões e fechadas para modificações Uma mudança deve ser concentrada, sem afetar demais módulos do sistema
Liskov Substituition Principle Subclasses devem ser substituíveis por sua classe mãe Simples caso de violação do princípio Quadrado x Retângulo
Interface Segregation Principle Clientes não podem ser forçados a dependerem de interfaces que não usam Interfaces pequenas e especícias para clientes
Dependency Inversion Principle Dependa de abstrações, não de concreções Favorece OCP
Anti-Patterns Um padrão que aponta como sair  De um problema para uma solução ruim  De uma solução ruim para uma solução boa Incentivados pela popularidade de Padrões de Projeto 1996,  Michael Ackoyd -  &quot; AntiPatterns: Vaccinations Against Object Misuse &quot;
Anti-Patterns The Big Ball of Mud Sistema sem arquitetura definida Overuse of Patterns Uso de  Design Patterns  sem necessidade God Objects Concentrar muitas responsabilidades à uma única classe Polter Geist Objetos usados apenas para passar informação
Anti-Patterns Geographically Distributed Development Integrantes de uma equipe geograficamente separados grande parte do tempo Accidental Complexity Introduzir complexidade desnecessária à solução Walking Through a Mine Field Incerteza sobre o comportamento de um componente Copy and Paste Programming Copiar código existente ao invés de criar soluções genéricas
Perguntas
Design Patterns com C# Fernando Kakimoto [email_address] www.twitter.com/nandokakimoto

[CLPE] Design patterns com c#

  • 1.
    Design Patterns comC# Fernando Kakimoto [email_address] www.twitter.com/nandokakimoto
  • 2.
    Quem Sou Eu?Centro de Informática - U.F.P.E. Graduado em Ciências da Computação (2008) Mestrando em Ciências da Computação Inove Informática Engenheiro de Software / Líder de Equipe Certificações MCP | MCTS Web 2.0 SCJP 6.0 Intereseses Arquitetura, metodologias ágeis, desenvolvimento Web
  • 3.
    Agenda Introdução ClassificaçãoAlguns padrões Princípios SOLID Anti-patterns
  • 4.
    Introdução “ Howcan you distribute responsibility for design through all levels of a large hierarchy, while still maintaining consistency and harmony of overall design?”
  • 5.
    Introdução Alexander sugeriuusar Padrões de Projeto Dicionário de termos relacionados a decisões básicas de projeto arquitetural Cada padrão descreve um problema comum do dia a dia e sua solução A solução pode ser reusada Discussões arquiteturais passaram a ser conduzidas por essa linguagem
  • 6.
    Introdução [GoF] DesignPatterns: Elements of Reusable Object-Oriented Software
  • 7.
    Introdução “ Adesign pattern names, abstracts, and identifies the key aspects of a common design structure that make it useful for creating a reusable object-oriented design .” - Gang of Four (Gamma et al.)
  • 8.
    Por que padrões?Procurar objetos apropriados Determinar granularidade dos objetos Estimular reuso Projetar mudanças
  • 9.
    Nomenclatura Nome Contrução de um vocabulário Problema Quando aplicar o padrão Solução Estrutura genérica de elementos Consequências Trade-offs da implementação
  • 10.
    Classificação Propósito CriacionalEstrutural Comportamental Escopo Classe Factory Method Adapter (class) Interpreter Template Method Objeto Abstract Factory Builder Prototype Singleton Adapter (object) Bridge Composite Decorator Facade Flyweight Proxy Chain of Responsability Command Iterator Mediator Memento Observer State Strategy Visitor
  • 11.
    Factory Method IntençãoMotivação Consequências Fornece uma interface para criação de famílias de objetos, sem especificar suas classes concretas A classe não pode antecipar o objeto que ela deve criar A classe precisa que a subclasse especifique o objeto criado Programação para interfaces Necessidade de subclasses Creator para criação de Products específicos
  • 12.
  • 13.
  • 14.
  • 15.
    Factory Method publicinterface Manipulator { void DownClick(); void Drag(); void UpClick(); } public class LineManipulator : Manipulator { public void DownClick() { Console. WriteLine( &quot;Line DownClick()&quot; ); } public void Drag() { Console. WriteLine( &quot;Line Drag()&quot; ); } public void UpClick() { Console. WriteLine( &quot;Line UpClick()&quot; ); } } public class TextManipulator : Manipulator { public void DownClick() { Console. WriteLine( “Text DownClick()&quot; ); } public void Drag() { Console. WriteLine( “Text Drag()&quot; ); } public void UpClick() { Console. WriteLine( “Text UpClick()&quot; ); } }
  • 16.
    Factory Method publicabstract class Figure { public Manipulator Manipulator { get; set; } public Figure() { CreateManipulator(); } public abstract void CreateManipulator(); public void DoSomething() { this .Manipulator.Drag(); } } public class LineFigure : Figure { public override void CreateManipulator() { this. Manipulator = new LineManipulator (); } } public class TextFigure : Figure { public override void CreateManipulator() { this .Manipulator = new TextManipulator (); } }
  • 17.
    Factory Method class Program { static void Main( string [ ] args) { Figure figure = new LineFigure (); figure.DoSomething(); figure = new TextFigure (); figure.DoSomething(); } }
  • 18.
    Decorator Intenção MotivaçãoConsequências Adiciona responsabilidades dinamicamente a um objeto Adicionar responsabilidades a objetos ao invés de classes Responsabilidades podem ser retiradas Quando extensão por herança é impraticável Mais flexibilidade do que heranças estáticas Evita explosão de classes Inúmeros objetos semelhantes
  • 19.
  • 20.
  • 21.
  • 22.
    Decorator public abstractclass LibraryItem { public int NumCopies { get; set; } public abstract void Display(); } public class Book : LibraryItem { private string Author; private string Title; public Book( string author , string title , int numCopies) { this. Author = author; this. Title = title; this. NumCopies = numCopies; } public override void Display() { Console. WriteLine( &quot;\n*** Book ***&quot; ); Console. WriteLine( &quot;Author: {0}&quot; , Author); Console. WriteLine( &quot;Title: {0}&quot; , Title); Console. WriteLine( &quot;#Copies: {0}&quot; , NumCopies); } }
  • 23.
    Decorator public class Decorator : LibraryItem { protected LibraryItem LibraryItem { get; set; } public Decorator( LibraryItem libraryItem) { this. LibraryItem = libraryItem; } public override void Display() { LibraryItem.Display(); } } public abstract class LibraryItem { public int NumCopies { get; set; } public abstract void Display(); }
  • 24.
    Decorator class Program { static void Main( string [ ] args) { Book book = new Book( &quot;Worley&quot;, &quot;Inside ASP.NET&quot; , 10); book.Display(); Borrowable borrowBook = new Borrowable (book); borrowBook.BorrowItem( &quot;Customer #1&quot; ); borrowBook.BorrowItem( &quot;Customer #2&quot; ); borrowBook.Display(); } } public class Borrowable : Decorator { public List < string > Borrowers { get ; private set ; } public Borrowable ( LibraryItem libraryItem ) : base (libraryItem) { this .Borrowers = new List < string >(); } public void BorrowItem( string name) { Borrowers.Add(name); this .LibraryItem.NumCopies- -; } public override void Display() { base. Display(); Borrowers.ForEach( b => Console.WriteLine ( &quot;borrower: {0}&quot; , b)); } }
  • 25.
    Observer Intenção MotivaçãoConsequências Define dependências entre objetos, tal que quando um objeto muda de estado, seus dependentes são notificados e atualizados Manter consistência entre objetos relacionados Manter baixo acoplamento Um objeto deve notificar outro objeto sem fazer suposições prévias Acoplamento abstrato entre Subject e Observer Suporte para comunicação broadcast Atualizações inesperadas
  • 26.
  • 27.
  • 28.
  • 29.
    Observer public abstractclass Subject <T> { private List < Observer <T>> Observers; public Subject() { this .Observers = new List < Observer <T>>(); } public void Attach( Observer <T> o) { this .Observers.Add(o); } public void Detach( Observer <T> o) { this .Observers.Remove(o); } public void Notify(T data) { this .Observers.ForEach(o => o.Update(data)); } } public class ClockTimer : Subject < DateTime > { public DateTime CurrentTime { get; set; } public ClockTimer( DateTime time) { this. CurrentTime = time; } public void Tick() { this. CurrentTime = DateTime .Now; this .Notify( this .CurrentTime); } }
  • 30.
    Observer public interface Observer <T> { void Update(T data); } public class AnalogicTimer : Observer < DateTime > { public void Update( DateTime time) { Console .WriteLine( &quot;AnalogicTimer {0}&quot; , time); } } public class DigitalTimer : Observer < DateTime > { public void Update( DateTime time) { Console .WriteLine( &quot;DigitalTimer {0}&quot; , time); } }
  • 31.
    Observer class Program { static void Main( string [ ] args) { ClockTimer timer = new ClockTimer ( DateTime .Now); AnalogicTimer analogicTimer = new AnalogicTimer (); timer.Attach(analogicTimer); DigitalTimer digitalTimer = new DigitalTimer (); timer.Attach(digitalTimer); timer.Tick(); timer.Detach(analogicTimer); Thread .Sleep(5000); timer.Tick(); } }
  • 32.
    Strategy Intenção MotivaçãoConsequências Define uma família de algoritmos, encapsula cada um, e os torna substituíveis. Configurar uma classe com um entre vários comportamentos Diferentes variação para um mesmo algoritmo Encapsula detalhes de implementação de um algoritmo Define um comportamento para contextos de reuso Alternativa a extensão de classes Elimina instruções condicionais
  • 33.
  • 34.
  • 35.
  • 36.
    Strategy public interface PersistenceStrategy <T> { void Save(T item); void Remove(T item); bool Exists(T item); } public class CollectionPersistence <T> : PersistenceStrategy <T> { public void Save(T item) { Console. WriteLine( &quot;CollectionPersistence: Save&quot; ); } public void Remove(T item) { Console .WriteLine( &quot;CollectionPersistence: Remove&quot; ); } public bool Exists(T item) { Console .WriteLine( &quot;CollectionPersistence: Exists&quot; ); return false; } }
  • 37.
    Strategy class Program { static void Main( string [ ] args) { Contact c = new Contact() { Name = &quot;Fernando Kakimoto&quot;, PhoneNumer = &quot;(81)9162-2997&quot;, Email = &quot;[email protected]&quot; }; PersistenceStrategy < Contact > persistence = new CollectionPersistence < Contact >(); persistence.Save(c); persistence.Remove(c); persistence.Exists(c); persistence = new DataBasePersistence < Contact >(); persistence.Save(c); persistence.Remove(c); persistence.Exists(c); } } public class DataBasePersistence <T> : PersistenceStrategy <T> { public void Save(T item) { Console .WriteLine( &quot;DataBasePersistence: Save&quot; ); } public void Remove(T item) { Console .WriteLine( &quot;DataBasePersistence: Remove&quot; ); } public bool Exists(T item) { Console .WriteLine( &quot;DataBasePersistence: Exists&quot; ); return false; } }
  • 38.
    SOLID Principles Expõeaspectos de gestão de dependência no desenvolvimento orientado à objetos Identifica código frágil e difícil de mudar/estender Base para as –ilities desejadas por desenvolvedores Março de 1995, Robert C. Martin
  • 39.
    SOLID Principles Single Responsability Principle O pen-Closed Principle L iskov Substituition Principle I nterface Segregation Principle D ependency Inversion Principle
  • 40.
    Single Responsability PrincipleUma classe deve ter uma única razão para mudar Uma responsabilidade é um eixo de mudança O que considerar como responsabilidade?
  • 41.
    Open-Closed Principle Entidadesde software devem ser abertas para extensões e fechadas para modificações Uma mudança deve ser concentrada, sem afetar demais módulos do sistema
  • 42.
    Liskov Substituition PrincipleSubclasses devem ser substituíveis por sua classe mãe Simples caso de violação do princípio Quadrado x Retângulo
  • 43.
    Interface Segregation PrincipleClientes não podem ser forçados a dependerem de interfaces que não usam Interfaces pequenas e especícias para clientes
  • 44.
    Dependency Inversion PrincipleDependa de abstrações, não de concreções Favorece OCP
  • 45.
    Anti-Patterns Um padrãoque aponta como sair De um problema para uma solução ruim De uma solução ruim para uma solução boa Incentivados pela popularidade de Padrões de Projeto 1996, Michael Ackoyd - &quot; AntiPatterns: Vaccinations Against Object Misuse &quot;
  • 46.
    Anti-Patterns The BigBall of Mud Sistema sem arquitetura definida Overuse of Patterns Uso de Design Patterns sem necessidade God Objects Concentrar muitas responsabilidades à uma única classe Polter Geist Objetos usados apenas para passar informação
  • 47.
    Anti-Patterns Geographically DistributedDevelopment Integrantes de uma equipe geograficamente separados grande parte do tempo Accidental Complexity Introduzir complexidade desnecessária à solução Walking Through a Mine Field Incerteza sobre o comportamento de um componente Copy and Paste Programming Copiar código existente ao invés de criar soluções genéricas
  • 48.
  • 49.
    Design Patterns comC# Fernando Kakimoto [email_address] www.twitter.com/nandokakimoto

Notas do Editor

  • #11 Escopo especifica se o padrão é aplicado ao objeto ou a classe. - classe: foca na relação de herança, fixos em tempo de compilação - objeto: foca na interação entre objetos, podendo ser mudados em tempo de execução Creational patterns abstract the object instantiation process: They hide how objects are created and help make the overall system independent of how its objects are created and composed. Structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.