23/10/15 Design Patterns / Padrões de Projeto Padrões de Projeto (Design Patterns) em Java João Paulo A. Almeida ([email protected]) http://nemo.inf.ufes.br Departamento de Informática Universidade Federal do Espírito Santo • Um padrão de projeto é uma solução geral para um problema recorrente • É uma espécie de “gabarito” para como resolver um problema • Captura boas práticas • Serve para criar uma linguagem de comunicação • (veja o livro de Gamma et. al. (GoF Gang of Four) intitulado “Design Patterns”) • Aqui alguns úteis aplicados a Java... SeparaçãodeImplementaçãoeInterface SeparaçãodeImplementaçãoeInterface • • • • • • Àsvezesaplicamosopadrãoatémesmoparaprever alteraçõesfuturas,edesacoplarousodoobjetoda implementação • Exemplo: interfaceProduct{publicvoidgetPrice();} classProductImplimplementsProduct{ publicvoidgetPrice(){…} } Uso:Productp=newProductImpl(); p.getPrice(); • Permitealteraçãofuturadaclassequeimplementa... Jávimosestepadrãoemaçãonascollec8onsdeJava: interfaceList<T> classArrayList<T>implementsList<T> classLinkedList<T>implementsList<T> Nestecasopermiteabstrairasimplementaçõesespecíficas deList(adependênciasóexistenacriação) • Uso: List<String>lista=newLinkedList<String>(); lista.add(“Teste”); … GoFPaaerns Factorypaaern • Crea8onalPaaerns • Outropadrãoqueescondeaindamaisosdetalhesde criação(incluindoqualaclasseusada) • Nãousamosooperadornew,maspedimosacriaçãopara umaclasseespecial:afábrica(Factory) – Factory – FactorywithFinder – Singleton • StructuralPaaerns – Decorator – Composite • BehaviouralPaaerns – Iterator – Observer/Listener 1 23/10/15 Factory pattern Factory: interface Nomes mais comuns ProductFactory +createProduct() ProductFactoryImpl +createProduct() interface Product { // qualquer definição do objeto bla bla bla } class ProductImpl implements Product { // qualquer definição do objeto bla bla bla } interface ProductFactory { Product createProduct(); } Factory: implementação Factory: outra implementação class ProductFactoryImpl implements ProductFactory { public Product createProduct() { // cria um objeto, decidindo qual a implementação return (Product) new ProductImpl(); } } interface ProductFactory { Product createProduct(int productCode); } class ProductFactoryImpl implements ProductFactory { public Product createProduct(int productCode) { // cria um objeto, decidindo qual a implementação if (productCode==1) return (Product) new Product1Impl(); else if (productCode==2) return (Product) new Product2Impl(); } } Dinâmica do Factory Pattern Exemploemuso client factory create() object1 object1 hello helloReturn hello helloReturn create object2 object2 publicclassConta { … } publicclassBanco{ privateSet<Conta>contas=newSet<Conta>(); ContacriaConta(){ Contac=newConta(); contas.add(c); returnc; } } 2 23/10/15 Factory c/ Finder interface Product { bla bla bla } Factory/Finder Pattern Dynamics : Client : Factory findByKey (“ImageXYZ”); interface ProductFactory { Product createProduct(keytype key); Product findByKey(keytype key); } : Product Primary Key Object operation • // exercício: que exceções seriam relevantes? • // sugerir implementação Singletonobject Singleton • Acessoaobjetoglobal • Aoinvésdeusarmétodoseatributosestá8cos,queseria umaoutraformadefazeristo publicclassSingleObject{ //createanobjectofSingleObject privatesta8cSingleObjectinstance=newSingleObject(); //maketheconstructorprivatesothatthisclasscannotbeinstan8ated privateSingleObject(){} //Gettheonlyobjectavailable publicsta8cSingleObjectgetInstance(){ returninstance; } publicvoidshowMessage(){ System.out.println("HelloWorld!"); } //métodosaqui } Singletonapar8rdeJava1.6 CompositePaaern packagemypackage; publicenumMyEnumSingleton{ INSTANCE; //métodosaqui } • Normalmenteusadoparaumaárvorede“containment” • Umelementodeummesmo8po“contém”elementosdo mesmo8po • Exemplo: classPasta { List<Pasta>subpastas=newLinkedList<Pasta>(); List<Arquivo>arquivos=newLinkedList<Arquivo>(); } //aimplementaçãopermi8rialaçosapesardenãoseraideia 3 23/10/15 CompositePaaern CompositePaaern CompositePaaern(degenerado) Decorator classFuncionario { Stringnome;doublesalario; List<Funcionario>subordinados= newLinkedList<Funcionario>(); } • TambémconhecidocomoWrapper • Permiteextenderfuncionalidadedeumaclasseexistentede umaformadiferentedaherança • Naverdadepermiteemtempodeexecuçãoextenderum objetoexistente Iterator(java.u8l.Iterator) ScanneréumIterator<String> interfaceIterator<E> { //Returnstrueiftheitera8onhasmoreelements booleanhasNext(); //Returnsthenextelementintheitera8on //podejogarNoSuchElementExcep8on Enext(); } IncorporadonascoleçõesdeJava,mastambémemScanner (naverdadeScannerimplementsIterator<String>) java.u8l.Scanners=newjava.u*l.Scanner("teste;;teste2"); s.useDelimiter(";"); System.out.println(s.hasNext()); System.out.println("["+s.next()+"]"); System.out.println(s.hasNext()); System.out.println("["+s.next()+"]"); System.out.println(s.hasNext()); System.out.println("["+s.next()+"]"); System.out.println(s.hasNext()); • JávimosusonocasodosReaders: • BufferedReaderéumDecoratordeFileReader,adicionando métodos • BufferedReaderin=newBufferedReader(new FileReader("foo.in")); • PassamosausaroBufferedReader,que“encapsula”o FileReader,adicionandomarkereset 4 23/10/15 “foreach”usaIterator… Observer ou Listener for(Pessoap:listapessoas) { System.out.println(p.getNome()); } PossívelparaqualquerclassequeimplementeIterable<T> publicinterfaceIterable<T> { Iterator<T>iterator(); } Listener/Observer interfaceListener { publicvoidno8fy(); } publicObserverimplementsListener { publicvoidno8fy() { System.out.println(“Contacriada”); } } Listener/Observer Exemploemuso interfaceListener { publicvoidno8fy(); } publicObserverimplementsListener { publicvoidno8fy() { System.out.println(“Contacriada”); } } publicclassBanco{ privateSet<Conta>contas=newSet<Conta>(); privateSet<Listener>listeners=newSet<Listener>(); publicaddListener(Listenerlistener){ listeners.add(listener); } publicremoveListener(Listenerlistener){ listener.remove(listener); } publicContacriaConta(){ Contac=newConta(); contas.add(c); for(Listenerlistener:listeners){listener.no8fy();} returnc; } } 5 23/10/15 Exemploemuso(Listener) publicsta8cvoidmain() { Bancob=newBanco(); Observero=newObserver(); b.addListener(o); b.criaConta(); } 6