|
|
(9 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| {{TOCright}}
| | #REDIRECT [[ist:Composite (padrão de desenho)]] |
| <!-- Material correspondente à aula 22. Â-->
| |
| O padrão ''composite'' organiza os objectos em árvores que representam hierarquias parte-todo. O uso do padrão permite que sejam tratados uniformemente os objectos e as suas composições.
| |
| | |
| == Estrutura ==
| |
| | |
| O padrão ''composite'' tem a seguinte estrutura de classes:
| |
| | |
| [[Image:composite-dpcd.png|600px]] | |
| | |
| ==Exemplo==
| |
| | |
| Um restaurante tem empregadas que apresentam menus aos clientes. Cada empregada dispõe de várias ementas, consoante a hora do dia: assim, existem ementas para pequenos almoços, almoços e jantares, por exemplo.
| |
| | |
| ===A Empregada Básica===
| |
| Uma implementação simples definiria na implementação do conceito ''empregada'' as referências para os objectos que representam as ementas.
| |
| | |
| <B>public</B> <B>class</B> Empregada0 {
| |
|
| |
| Ementa _ementaPequenoAlmoço;
| |
| Ementa _ementaAlmoço;
| |
| Ementa _ementaLanche;
| |
|
| |
| <B>public</B> <FONT COLOR="#000080">Empregada0</FONT>(Ementa ementaPequenoAlmoço, Ementa ementaAlmoço,
| |
| Ementa ementaLanche) {
| |
| _ementaPequenoAlmoço = ementaPequenoAlmoço;
| |
| _ementaAlmoço = ementaAlmoço;
| |
| _ementaLanche = ementaLanche;
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">printMenu</FONT>() {
| |
| <FONT COLOR="#000080">printMenu</FONT>(ementaAlmoço);
| |
| <FONT COLOR="#000080">printMenu</FONT>(ementaLanche);
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">printMenu</FONT>(Ementa ementa) {
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">println</FONT>(ementa.<FONT COLOR="#000080">nome</FONT>());
| |
| <B>for</B> (ItemEmenta item : ementa)
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out.printf</FONT>(<FONT COLOR="#dd0000">"</FONT><FONT COLOR="#ff00ff">%s</FONT><FONT COLOR="#dd0000">, </FONT><FONT COLOR="#ff00ff">%s%n </FONT><FONT COLOR="#dd0000">-- </FONT><FONT COLOR="#ff00ff">%s%n</FONT><FONT COLOR="#dd0000">"</FONT>, item.nome(),
| |
| item.<FONT COLOR="#000080">preço</FONT>(), item.<FONT COLOR="#000080">descrição</FONT>());
| |
| }
| |
|
| |
| }
| |
| | |
| Esta situação conduz a inflexibilidade na manutenção: por exemplo, a adição de novas refeições implica a alteração das empregadas!
| |
| | |
| ===Refeições a todas as horas===
| |
| Uma possÃvel solução é definir as empregadas como tendo, não dois, três, ou um número concreto de ementas, mas sim como tendo a capacidade de gerir um número indeterminado (uma colecção) de ementas.
| |
| | |
| <B>import</B><FONT COLOR="#808000"> java.util.ArrayList;</FONT>
| |
|
| |
| <B>public</B> <B>class</B> Empregada1 {
| |
|
| |
| <B><FONT COLOR="#0095ff">ArrayList</FONT></B><Ementa> _ementas;
| |
|
| |
| <B>public</B> <FONT COLOR="#000080">Empregada1</FONT>(<B><FONT COLOR="#0095ff">ArrayList</FONT></B><Ementa> ementas) {
| |
| _ementas = ementas;
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">printMenu</FONT>() {
| |
| <B>for</B> (Ementa ementa : _ementas) <FONT COLOR="#000080">printMenu</FONT>(ementa);
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">printMenu</FONT>(Ementa ementa) {
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">println</FONT>(ementa.<FONT COLOR="#000080">nome</FONT>());
| |
| <B>for</B> (ItemEmenta item : ementa)
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out.printf</FONT>(<FONT COLOR="#dd0000">"</FONT><FONT COLOR="#ff00ff">%s</FONT><FONT COLOR="#dd0000">, </FONT><FONT COLOR="#ff00ff">%s</FONT><FONT COLOR="#dd0000">%n -- </FONT><FONT COLOR="#ff00ff">%s%n</FONT><FONT COLOR="#dd0000">"</FONT>, item.nome(),
| |
| item.<FONT COLOR="#000080">preço</FONT>(), item.<FONT COLOR="#000080">descrição</FONT>());
| |
| }
| |
|
| |
| }
| |
| | |
| ===Sobremesas ao Jantar===
| |
| Mas o que aconteceria se se quisesse adicionar uma outra ementa apenas a uma das refeições? Por exemplo, adicionar uma ementa de sobremesas ou uma carta de vinhos à ementa do jantar. A solução anterior não tem limitações ao número de ementas que uma empregada pode gerir. No entanto, adicionar uma ementa à colecção não a associa de forma alguma à ementa do jantar: seria necessário alterar o código da empregada para fazer tal associação: uma situação indesejável. A solução passa por utilizar o padrão de composição (''composite''): por um lado a ementa do jantar vai ter uma outra ementa como se fosse mais uma entrada, por outro a empregada trata a ementa do jantar como sempre fez (i.e., sem alterações).
| |
| | |
| <B>public</B> <B>abstract</B> <B>class</B> ComponenteEmenta {
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">adicionar</FONT>(ComponenteEmenta componente) {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
|
| |
| <B>public</B> ComponenteEmenta <FONT COLOR="#000080">obtémFilho</FONT>(<FONT COLOR="#800000">int</FONT> i) {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
|
| |
| <B>public</B> <B><FONT COLOR="#0095ff">String</FONT></B> <FONT COLOR="#000080">nome</FONT>() {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
|
| |
| <B>public</B> <B><FONT COLOR="#0095ff">String</FONT></B> <FONT COLOR="#000080">descrição</FONT>() {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">double</FONT> <FONT COLOR="#000080">preço</FONT>() {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">boolean</FONT> <FONT COLOR="#000080">vegetariano</FONT>() {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">print</FONT>() {
| |
| <B>throw</B> <B>new</B> <B><FONT COLOR="#0095ff">UnsupportedOperationException</FONT></B>();
| |
| }
| |
| }
| |
| | |
| <B>public</B> <B>class</B> Ementa <B>extends</B> ComponenteEmenta {
| |
| <B><FONT COLOR="#0095ff">ArrayList</FONT></B><ComponenteEmenta> _componentes = <B>new</B> <B><FONT COLOR="#0095ff">ArrayList</FONT></B><ComponenteEmenta>();
| |
| <B><FONT COLOR="#0095ff">String</FONT></B> _nome;
| |
| <B><FONT COLOR="#0095ff">String</FONT></B> _descrição;
| |
|
| |
| <B>public</B> <FONT COLOR="#000080">Ementa</FONT>(<B><FONT COLOR="#0095ff">String</FONT></B> nome, <B><FONT COLOR="#0095ff">String</FONT></B> descrição) {
| |
| _nome = nome;
| |
| _descrição = descrição;
| |
| }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">adicionar</FONT>(ComponenteEmenta componente) {
| |
| _componentes.<FONT COLOR="#000080">add</FONT>(componente);
| |
| }
| |
|
| |
| <B>public</B> ComponenteEmenta <FONT COLOR="#000080">obtémFilho</FONT>(<FONT COLOR="#800000">int</FONT> i) {
| |
| <B>return</B> _componentes.<FONT COLOR="#000080">get</FONT>(i);
| |
| }
| |
|
| |
| <B>public</B> <B><FONT COLOR="#0095ff">String</FONT></B> <FONT COLOR="#000080">nome</FONT>() { <B>return</B> _nome; }
| |
| <B>public</B> <B><FONT COLOR="#0095ff">String</FONT></B> <FONT COLOR="#000080">descrição</FONT>() { <B>return</B> _descrição; }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">print</FONT>() {
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out.printf</FONT>(<FONT COLOR="#dd0000">"</FONT><FONT COLOR="#ff00ff">%n%s</FONT><FONT COLOR="#dd0000">, </FONT><FONT COLOR="#ff00ff">%s%n</FONT><FONT COLOR="#dd0000">"</FONT>, nome(), descrição());
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">println</FONT>(<FONT COLOR="#dd0000">"--------------------"</FONT>);
| |
| <B>for</B> (ComponenteEmenta componente : _componentes)
| |
| componente.<FONT COLOR="#000080">print</FONT>();
| |
| }
| |
| }
| |
| | |
| <B>public</B> <B>class</B> ItemEmenta <B>extends</B> ComponenteEmenta {
| |
|
| |
| <B><FONT COLOR="#0095ff">String</FONT></B> _nome;
| |
| <B><FONT COLOR="#0095ff">String</FONT></B> _descrição;
| |
| <FONT COLOR="#800000">boolean</FONT> _vegetariano;
| |
| <FONT COLOR="#800000">double</FONT> _preço;
| |
|
| |
| <B>public</B> <FONT COLOR="#000080">ItemEmenta</FONT>(<B><FONT COLOR="#0095ff">String</FONT></B> nome, <B><FONT COLOR="#0095ff">String</FONT></B> descrição, <FONT COLOR="#800000">boolean</FONT> vegetariano, <FONT COLOR="#800000">double</FONT> preço) {
| |
| _nome = nome;
| |
| _descrição = descrição;
| |
| _vegetariano = vegetariano;
| |
| _preço = preço;
| |
| }
| |
|
| |
| <B>public</B> <B><FONT COLOR="#0095ff">String</FONT></B> <FONT COLOR="#000080">nome</FONT>() { <B>return</B> _nome; }
| |
| <B>public</B> <B><FONT COLOR="#0095ff">String</FONT></B> <FONT COLOR="#000080">descrição</FONT>() { <B>return</B> _descrição; }
| |
| <B>public</B> <FONT COLOR="#800000">double</FONT> <FONT COLOR="#000080">preço</FONT>() { <B>return</B> _preço; }
| |
| <B>public</B> <FONT COLOR="#800000">boolean</FONT> <FONT COLOR="#000080">vegetariano</FONT>() { <B>return</B> _vegetariano; }
| |
|
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">print</FONT>() {
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">print</FONT>(<FONT COLOR="#000080">nome</FONT>());
| |
| <B>if</B> (<FONT COLOR="#000080">vegetariano</FONT>()) <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">print</FONT>(<FONT COLOR="#dd0000">" (v)"</FONT>);
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">println</FONT>(<FONT COLOR="#dd0000">", "</FONT> + <FONT COLOR="#000080">preço</FONT>());
| |
| <B><FONT COLOR="#0095ff">System</FONT></B>.<FONT COLOR="#000080">out</FONT>.<FONT COLOR="#000080">println</FONT>(<FONT COLOR="#dd0000">" -- "</FONT> + <FONT COLOR="#000080">descrição</FONT>());
| |
| }
| |
| }
| |
| | |
| <B>public</B> <B>class</B> Empregada2 {
| |
| <B>private</B> ComponenteEmenta _ementas;
| |
| <B>public</B> <FONT COLOR="#000080">Empregada2</FONT>(ComponenteEmenta ementas) { _ementas = ementas; }
| |
| <B>public</B> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">printMenu</FONT>() { _ementas.<FONT COLOR="#000080">print</FONT>(); }
| |
| }
| |
| | |
| <B>public</B> <B>class</B> Restaurante {
| |
| <B>public</B> <FONT COLOR="#800000">static</FONT> <FONT COLOR="#800000">void</FONT> <FONT COLOR="#000080">main</FONT>(<B><FONT COLOR="#0095ff">String</FONT></B>[] args) {
| |
| ComponenteEmenta pequenoAlmoço = <B>new</B> <FONT COLOR="#000080">Ementa</FONT>(<FONT COLOR="#dd0000">"PEQUENO ALMOÇO"</FONT>, <FONT COLOR="#dd0000">"Pequeno Almoço"</FONT>);
| |
| ComponenteEmenta almoço = <B>new</B> <FONT COLOR="#000080">Ementa</FONT>(<FONT COLOR="#dd0000">"ALMOÇO"</FONT>, <FONT COLOR="#dd0000">"Almoço"</FONT>);
| |
| ComponenteEmenta lanche = <B>new</B> <FONT COLOR="#000080">Ementa</FONT>(<FONT COLOR="#dd0000">"LANCHE"</FONT>, <FONT COLOR="#dd0000">"Lanche"</FONT>);
| |
| ComponenteEmenta jantar = <B>new</B> <FONT COLOR="#000080">Ementa</FONT>(<FONT COLOR="#dd0000">"JANTAR"</FONT>, <FONT COLOR="#dd0000">"Jantar"</FONT>);
| |
| ComponenteEmenta sobremesas = <B>new</B> <FONT COLOR="#000080">Ementa</FONT>(<FONT COLOR="#dd0000">"SOBREMESAS"</FONT>, <FONT COLOR="#dd0000">"Hmmmm!"</FONT>);
| |
|
| |
| ComponenteEmenta refeições = <B>new</B> <FONT COLOR="#000080">Ementa</FONT>(<FONT COLOR="#dd0000">"REFEIÇÕES"</FONT>, <FONT COLOR="#dd0000">"Tudo!"</FONT>);
| |
|
| |
| refeições.<FONT COLOR="#000080">adicionar</FONT>(pequenoAlmoço);
| |
| refeições.<FONT COLOR="#000080">adicionar</FONT>(almoço);
| |
| refeições.<FONT COLOR="#000080">adicionar</FONT>(lanche);
| |
| refeições.<FONT COLOR="#000080">adicionar</FONT>(jantar);
| |
|
| |
| jantar.<FONT COLOR="#000080">adicionar</FONT>(<B>new</B> <FONT COLOR="#000080">ItemEmenta</FONT>(<FONT COLOR="#dd0000">"Esparguete"</FONT>, <FONT COLOR="#dd0000">"Esparguete com deliciosas alcaparras"</FONT>,
| |
| <B>true</B>, <FONT COLOR="#800080">5.49</FONT>));
| |
| jantar.<FONT COLOR="#000080">adicionar</FONT>(sobremesas);
| |
|
| |
| Empregada2 empregada = <B>new</B> <FONT COLOR="#000080">Empregada2</FONT>(refeições);
| |
| empregada.<FONT COLOR="#000080">printMenu</FONT>();
| |
| }
| |
| }
| |
| | |
| [[category:OOP]]
| |
| [[category:Teaching]]
| |