Olá pessoal encontrei um outro tópico muito interessante sobre construção de objetos, para quem quiser dar uma olhada aí vai o link
http://www.coderanch.com/t/476548/Programmer-Certification-SCJP/certification/with-instance-initializer
questão interessante sobre OO
16 Respostas
É interessante sim, reflita sobre isso e pense como pode utilizar a seu favor.
Já trabalhei num projeto que utilizávamos isto ao nosso favos, a gente extendia todas as classes do Swing fazendo-os também realizar comportamentos de persistência em beans, trabalhando num estilo parecido com JSF.
Pesquise sobre o design pattern Decorator que também trabalha sobre este cenário.
Sim, mas você não deve chamar métodos que não sejam finais no construtor. Isso porque, a parte da classe correspondente ao filho ainda não foi construída. Nenhum atributo de lá é válido e, caso o método altere algum valor de atributo, esse valor será descartado. Isso pode gerar erros dificílimos de se corrigir, sem falar em comportamento inesperado do sistema.
O padrão decorator não usa esse princípio, pois ele nem necessariamente envolve herança.
O padrão decorator não usa esse princípio, pois ele nem sequer envolve herança.
Decorator sim envolve herança (http://en.wikipedia.org/wiki/Decorator_pattern).
Acho que vc está confundindo com Visitor (que não envolve herança e tb permite adicionar mais funcionalidades)
O padrão decorator não usa esse princípio, pois ele nem sequer envolve herança.Decorator sim envolve herança (http://en.wikipedia.org/wiki/Decorator_pattern).
Acho que vc está confundindo com Visitor (que não envolve herança e tb permite adicionar mais funcionalidades)
Na maior parte das vezes, uso o decorator baseando em uma interface, não numa classe concreta. Mas realmente, no padrão descrito pelo GoF, fala-se em herança. Em todo caso, a idéia central do decorator é embutir funcionalidades usando-se para isso composição e não herança.
O padrão decorator não usa esse princípio, pois ele nem sequer envolve herança.Decorator sim envolve herança (http://en.wikipedia.org/wiki/Decorator_pattern).
Acho que vc está confundindo com Visitor (que não envolve herança e tb permite adicionar mais funcionalidades)Na maior parte das vezes, uso o decorator baseando em uma interface, não numa classe concreta. Mas realmente, no padrão descrito pelo GoF, fala-se em herança. Em todo caso, a idéia central do decorator é embutir funcionalidades usando-se para isso composição e não herança.
O decorador tem que ser do mesmo tipo que o original. Mesmo que o original seja uma interface vc tem que implementar a mesma interface. A relação “o decorador É-UM X” é mantida, e por conseguinte a relação de herança, mesmo que vc não use a keyword extends.
O padrão usa herança no sentido que mantem a relação É-UM e o principio de substituição se aplica, não que ele usa necessáriamente extends.
O decorador tem que ser do mesmo tipo que o original. Mesmo que o original seja uma interface vc tem que implementar a mesma interface. A relação “o decorador É-UM X” é mantida, e por conseguinte a relação de herança, mesmo que vc não use a keyword extends.O padrão usa herança no sentido que mantem a relação É-UM e o principio de substituição se aplica, não que ele usa necessáriamente extends.
A herança do decorator existe para garantir compatibilidade da interface do decorador e o decorado. Entretanto, o padrão baseia-se extensão de funcionalidade por composição. Isso evita, por exemplo, que uma classe “JanelaComBorda” seja criada como filha da classe “Janela”, o que usaria o princípio demonstrado pelo autor do tópico, e reforça o uso da herança como mecanismo de extensão de funcionalidade.
Decorador e decorado não precisam ter qualquer relação é um. Um exemplo disso é um decorator que, por exemplo, gera estatísticas sobre o objeto decorado. A única relação entre eles seria “realizam a interface X”, o que não necessariamente implica em relação de herança. Embora a interface seja a mesma, o decorador terá um papel (por exemplo, gerar estatísticas), e o decorado outro (por exemplo, trafegar dados num canal).
No nosso caso nós criamos uma interface para cada componente da view e também extendemos as classes do Swing (JTextField, JButton, etc) para classes nossas que adicionam funcionalidades e que também implementam as interfaces anteriormente citadas.
Aí criamos uma classe Factory que cria os componentes view e retorna sob a interface anteriormente citada.
No caso o componente foi criado para, sob as mesmas interfaces, servir tanto para componentes Swing quando para componentes SWT. Então a gente passava por parâmetro se desejaria um componente baseado em Swing ou SWT e ele retornava o objeto sob a mesma interface.
Portanto tinhamos uma família de componentes baseados em SWT e uma família de componentes baseados em Swing. Pois eram os requisitos dos analistas do projeto até então.
Na minha opinião utilizamos sim o padrão Decorator, além de outros como Factory, Command (para as ações dos componentes botões) e Observer (para os listeners da nossa camada de persistência serem refletidos na view).
Decorador e decorado não precisam ter qualquer relação é um. Um exemplo disso é um decorator que, por exemplo, gera estatísticas sobre o objeto decorado. A única relação entre eles seria “realizam a interface X”, o que não necessariamente implica em relação de herança. Embora a interface seja a mesma, o decorador terá um papel (por exemplo, gerar estatísticas), e o decorado outro (por exemplo, trafegar dados num canal).
LoL… então vamos lá:
Se o decorador não precisa ter relação É-UM com o decorado , porquê vc precisa que o decorador implemente a mesma interface que o decorado ?
Se a sua tese fosse verdade , Comparable poderia ser um decorador de List.
Se A implementa a interface I e B também, e B é composto de A, e B não tem nenhum método a mais que A, B não é um decorador, é um proxy.
Decorador implica que B seja A no sentido de principio de substituição de Liskov(http://en.wikipedia.org/wiki/Liskov_substitution_principle) e além disso ele tem métodos que A não tem.
Ou seja, vc pode passar B onde seria esperado um A, e além disso tem acesso a métodos que não são acessíveis em A.
Adapter, Decorator, Proxy e Façade são muito semelhantes na implementação, mas são as subtilezas que os tornam diferentes.
A relação É-UM está ligada ao principio Liskov assim como a herança, os três são principios gerais de OO.
O fato do java distinguir entre herança e implementação não é relevante pois o padrão Decorator é agnóstico à linguagem.
Estou entendo direito, ou você quer me convencer que relação de herança entre classes e implementação de interfaces significam a mesma coisa?
Duas classes completamente diferentes podem implementar a mesma interface, e estarem relacionadas única e exclusivamente por isso. Considere, por exemplo, o que faz o BufferedInputStream. Ele apenas decora um stream, dando a ele uma funcionalidade a mais, a presença de um buffer. Mas ele, por si só, não é um stream e, portanto, não se trata de herança. O mesmo vale para outras classes do java como SychronizedCollection, ou mesmo UnmodifiableList (que inclusive nega o princípio de Liskov).
Em momento nenhum eu disse que ele só poderia ter métodos de A. De onde você tirou isso? Aliás, que eu me lembre, a única imposição do decorator é que ele deve adicionar um comportamento, não que isso deva implicar necessariamente na adição de novos métodos.
Concordo. Não estou falando em uma linguagem específica, também.
A diferença entre um decorator e um proxy nem sequer é essa. O decorator foca-se em adicionar funcionalidades dinamicamente a objetos. Aliás, é essa característica dele, que digo que nega o princípio de herança, uma vez que herança envolve em ampliar a funcionalidade de classes.
Já o proxy, é relacionado servir de interface para alguém.
Até por isso, tipicamente, criamos o objeto decorado externamente, e adicionamos a ele o decorator. Enquanto o objeto proxiado geralmente é criado internamente, dentro do proxy (obviamente o proxy pode delegar essa tarefa para uma fábrica, mas normalmente fará isso dentro sua parte privada).
Estou entendo direito, ou você quer me convencer que relação de herança entre classes e implementação de interfaces significam a mesma coisa?
Para o padrão sim. Por isso que eu disse que o fato do java separar o que herança de classe do que é implementação de interfaces não pode ser usado para dizer que o decorator não usa herança.
Em scala, por exemplo, vc tem traits que não são nem interfaces nem classes, são um conceito diferente. E eles são decorators por design.
O ponto é que "o conceito de herança" está relacionada a "É-UM", sempre. Independentemente da linguagem entender assim ou não.
Na realidade não. Os métodos de list tem implementações optionais, logo uma umodifiableList sim substitui um list.
quanto ao buffer ele é um InputStream sim, o que o torna um decorator. Ele É-UM InputStream e ele é composto por um InputStream. Ser X e ter um X é a condição sin qua non para ser um decorator. A outra é ter funcionaliade extra. e funcionalidade significa métodos extra e não implementação diferente ( isso é um proxy). BufferInputStream não fecha este requisito, o que o torna um proxy e não um decorator. como disse, a diferença é subtil. Mas por exemplo ByteArrayOutputStream é claramente um decorator de OutputStream já que ele tem o método toByteArray() que não existe em OutputStream.
Decorator => existe composição de um objeto do tipo X em um objeto da hierarquia de X + métodos adicionais.
O decorator sempre pode substituir o decorado
Proxy => existe composição de um objeto do tipo X em um objeto da hierarquia de X + implementação diferente
O proxy sempre pode substituir o "proxizado"
Não. Tem que haver novos métodos, caso contrário é um proxy. A menos que vc ache que proxy e decorator são nomes para o mesmo padrão. (eu não acho)
Ok, Sergio. Pode apenas me citar no livro do GoF, onde diz que o decorator precisa ter novos métodos para não ser um proxy?
Estou com ele aberto aqui e não achei.
Eu entendo por funcionalidade extra não a presença de métodos, mas o serviço que a classe presta. O BufferedInputStream agrega um buffer, logo, ele tem uma funcionalidade extra. Ele também tem um objeto agregado. Além disso, o papel dele não é controlar acesso, e sim acrescentar essa funcionalidade. Portanto, um decorator. Aliás, o próprio exemplo do livro do GoF envolve streams, e ele nem sequer dá a entender que métodos extras são necessários.
A diferença entre o decorator e o proxy está na motivação.
O proxy necessariamente representa um outro objeto, e geralmente tem o papel de controlar o acesso. Ele geralmente vai se comportar exatamente como o objeto representado, quando ele julgar que deve responder por aquele objeto.
O decorator tem o papel de acrescentar funcionalidade.
A presença ou não de métodos adicionais não é obrigatória em nenhum dos casos.
Sergio vc esta confundindo herança com encapsulamento, já que vc citou a wilkpedia, vou usar a mesma fonte.
Isso citado acima é implementar uma interface não tem haver com a definição de herança.
Quando se implementa uma interface, não existe generalização, não se aproveita comportamento, e muito menos as propriedades, já que nem se define propriedades em uma interface.
Agora quanto da definição de Decorator e Proxy eu prefiro nem entrar no merito, pois para mim, o importante do padrão é o problema que ele resolve, de forma extensível e reutilizavel. Diferenças de implementação sempre irão surgir de acordo com o caso\linguagem de programação utilizada.
Nessa eu não entendi traits são decorators por design?
Vc poderia me explicar prq um trait é um decorator por design?
Ok, Sergio. Pode apenas me citar no livro do GoF, onde diz que o decorator precisa ter novos métodos para não ser um proxy?
Estou com ele aberto aqui e não achei.
E não vai achar mesmo. O GoF não é o unico catalogo de padrões do mundo.
Se fosse, o padrão Proxy não existiria pois não consta desse catálogo.
Como eu disse antes, se vc considerar que Decorator não envolve métodos a mais, então Decorator é a mesma coisa que Proxy. sem distinção. São dois nomes para a mesma coisa. Isso não faz muito sentido quando a mim.
Como eu tb já disse, eu não considero que sejam a mesma coisa, e portanto, quanto a mim sim existe uma distinção. E não sou o único.
“Adding functions”, não “adding functionality”. (veja no diagrama que existe um método a mais chamado Adicionalbehavior)
Porque ele não distinguem entre Decorator, Wrapper e Proxy. tudo bem se vc for por esse caminho, mas vc tem que explicitamente dizer isso, pois existe outra corrente dizendo que existem diferenças.
O decorator tem o papel de acrescentar funcionalidade.A presença ou não de métodos adicionais não é obrigatória em nenhum dos casos.
O decorator tem a missão de adicional funções ( aka método) , não funcionalidade. Funcionalidade todos os padrões de encapsulamento acrescentam. (function, não “functionality”)
Veja os diagramas sobre o decorator, sempre vc vai ver um método a mais que não existe na classe decorada. É esse método que é o objetivo do padrão. Acho que o site acima deixa clara a diferença, basta olhar os diagramas.
Em scala, por exemplo, vc tem traits que não são nem interfaces nem classes, são um conceito diferente. E eles são decorators por design.
Nessa eu não entendi traits são decorators por design?
Traits existem para adicionar funcões a classes que não as têm,mas eles têm que ser amarrados à classe logo, eles são decoradores dessa classe.
http://www.evolutionnext.com/blog/entry/title/Decorator+Pattern+In+Scala.html