(→2.4. Operações com redo/undo) |
(→2.9. Exercício de programação (formas de apresentação)) |
||
(12 intermediate revisions by the same user not shown) | |||
Line 177: | Line 177: | ||
[[Image:UML-teste-po-Janeiro-2009.png|frame|right| Figura 1]] | [[Image:UML-teste-po-Janeiro-2009.png|frame|right| Figura 1]] | ||
− | '''1.1.''' Considere o diagrama UML (à direita). Qual das seguintes afirmações está correcta? | + | '''1.1.''' Considere o diagrama UML (Figura 1, à direita). Qual das seguintes afirmações está correcta? |
:#<s>é sempre possível fazer casts de referências do tipo A para as do tipo I</s> | :#<s>é sempre possível fazer casts de referências do tipo A para as do tipo I</s> | ||
:#<s>doThat está acessível através do tipo I</s> | :#<s>doThat está acessível através do tipo I</s> | ||
Line 252: | Line 252: | ||
Aspectos importantes: | Aspectos importantes: | ||
− | * acesso privilegiado à classe contentora | + | * acesso privilegiado à classe contentora; |
− | * encapsulamento da classe interna pela contentora (eventualmente protegido) | + | * encapsulamento da classe interna pela contentora (eventualmente protegido); |
− | * implementação de interfaces externas por código protegido | + | * implementação de interfaces externas por código protegido. |
− | Exemplos: comparadores | + | Exemplos: |
+ | * comparadores de Strings Java; | ||
+ | * [[Classes Internas (Java)|Gato e Estômago]] (em que o estômago é implementado pelo gato, mas obedecendo a interface exterior); | ||
+ | * iteradores e colecções em Java. | ||
===2.2. State & Strategy === | ===2.2. State & Strategy === | ||
Line 266: | Line 269: | ||
Padrão comando: encapsulamento de operações como objectos. | Padrão comando: encapsulamento de operações como objectos. | ||
− | Métodos a implementar nos comandos do/redo e undo. | + | Métodos a implementar nos comandos: |
+ | * do/redo e | ||
+ | * undo. | ||
===2.5.1. Saída do programa=== | ===2.5.1. Saída do programa=== | ||
Line 277: | Line 282: | ||
===2.6. Diagrama de classes (UML) === | ===2.6. Diagrama de classes (UML) === | ||
− | Esboço do diagrama de classes para o problema apresentado. | + | Esboço do diagrama de classes para o problema apresentado (foram omitidas algumas setas para não sobrecarregar o diagrama: na resolução completa, deveriam ser incluídas). |
[[Image:PO-Janeiro2009-class.png]] | [[Image:PO-Janeiro2009-class.png]] | ||
Line 290: | Line 295: | ||
===2.9. Exercício de programação (formas de apresentação)=== | ===2.9. Exercício de programação (formas de apresentação)=== | ||
+ | |||
+ | Uso do padrão Visitor: uma classe de visita por forma de apresentação. | ||
+ | |||
+ | <source lang="java"> | ||
+ | import java.util.ArrayList; | ||
+ | abstract class Printable { | ||
+ | public void add(Printable p) { throw new UnsupportedOperationException(); } | ||
+ | public abstract String accept(Printer v); | ||
+ | } | ||
+ | |||
+ | class Paragraph extends Printable { | ||
+ | public String accept(Printer v) { return v.showParagraph(this); } | ||
+ | } | ||
+ | |||
+ | class Image extends Printable { | ||
+ | public String accept(Printer v) { return v.showImage(this); } | ||
+ | } | ||
+ | |||
+ | class Album extends Printable { | ||
+ | public ArrayList<Printable> _printables = new ArrayList<Printable>(); | ||
+ | public void add(Printable p) { _printables.add(p); } | ||
+ | public List<Printable> getPrintables() { return _printables; } | ||
+ | public String accept(Printer v) { return v.showAlbum(this); } | ||
+ | } | ||
+ | |||
+ | class Page extends Album { | ||
+ | public String accept(Printer v) { return v.showPage(this); } | ||
+ | } | ||
+ | |||
+ | class Book extends Album { | ||
+ | public String accept(Printer v) { return v.showBook(this); } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | As formas de apresentação são as definidas pela hierarquia de visita abaixo: <code>Printer</code> abstrai o conceito de apresentação; <code>ShowWithBrackets</code> representa a forma de apresentação presente no código original. Novas formas de apresentação resumem-se à definição de classes como esta última e não implicam quaisquer alterações no restante código. | ||
+ | <source lang="java"> | ||
+ | interface Printer { | ||
+ | String showParagraph(Paragraph p); | ||
+ | String showImage(Image i); | ||
+ | String showAlbum(Album a); | ||
+ | String showPage(Page p); | ||
+ | String showBook(Book b); | ||
+ | } | ||
+ | |||
+ | class ShowWithBrackets implements Printer { | ||
+ | public String showParagraph(Paragraph p) { return "[paragraph]"; } | ||
+ | public String showImage(Image i) { return "[image]"; } | ||
+ | public String showAlbum(Album a) { | ||
+ | String s = "["; | ||
+ | for (Printable p: a.getPrintables()) s += p.accept(this); | ||
+ | s += "]"; | ||
+ | return s; | ||
+ | } | ||
+ | public String showPage(Page p) { return showAlbum(p); } | ||
+ | public String showBook(Book b) { return showAlbum(b); } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Note-se que se reutilizou a implementação para Album na apresentação de Page e de Book (tal como acontecia no código original). | ||
[[category:PO]] | [[category:PO]] | ||
[[category:Ensino]] | [[category:Ensino]] |
1.1. Considere o diagrama UML (Figura 1, à direita). Qual das seguintes afirmações está correcta?
1.2. A definição de métodos, por uma classe, de métodos especificados numa interface, designa-se por:
1.3. Em Java, qual das seguintes frases está correcta?
1.4. A definição de uma classe por agregação de objectos de outras classes ou suas colecções designa-se por:
1.5. Em Java, a operação de serialização...
1.6. Em Java, relativamente à redefinição de métodos...
1.7. Em Java, uma classe anónima...
1.8. A utilização do padrão de desenho Façade...
1.9. O padrão de desenho Visitor...
1.10. O padrão de desenho Abstract Factory...
2.1. (1.5 val.) As classes internas em Java apresentam características que as tornam num mecanismo interessante para realizar de forma simples tarefas cujo encapsulamento poderia revelar-se complexo. Descreva as características de uma classe interna em Java e descreva um exemplo onde sejam evidenciadas vantagens da sua utilização.
2.2. (1.0 val.) Os padrões de desenho State e Strategy apresentam várias características comuns, tanto na estrutura, como na execução das operações. Acha que são intercambiáveis, ou que, pelo contrário, os casos de uso são diferentes? Justifique.
2.3. (1.5 val.) O conceito abstracto de interface representa um mecanismo poderoso na programação modular em geral e na programação por objectos em particular. Explique (por palavras suas) em que consistem as vantagens do desenvolvimento baseado em interfaces e que formas o Java tem de o disponibilizar.
2.4. (1.5 val.) Considere o seguinte problema. Um editor gráfico realiza manipulações sobre as entidades que aparecem na área de desenho (imagens, polígonos, caixas de texto, etc.). É desejável que cada operação possa ser reproduzida ou invertida, tendo, para tal, de ser guardada. Que padrão de desenho pode ser usado? Explique como o usaria.
2.5.1. (1.0 val.) Qual o resultado que se obtém quando se executa o programa? (represente mudanças de linha com \n) <java5> import java.util.ArrayList; abstract class Printable {
public abstract String show(); public void add(Printable p) { throw new UnsupportedOperationException(); }
}
class Paragraph extends Printable {
public String show() { return "[paragraph]"; }
}
class Image extends Printable {
public String show() { return "[image]"; }
}
class Album extends Printable {
public ArrayList<Printable> _printables = new ArrayList<Printable>(); public void add(Printable p) { _printables.add(p); } public String show() { String s = "["; for (Printable p: _printables) s += p.show(); s += "]"; return s; }
}
class Page extends Album {} class Book extends Album {}
public class App {
public static void main(String args[]) { Page page1 = new Page(); page1.add(new Paragraph()); page1.add(new Image()); Page page2 = new Page(); //!2.7 page2.add(new Paragraph()); //!2.7 page2.add(new Image()); //!2.7 Book book = new Book(); book.add(page1); book.add(page2); //!2.7 System.out.println(book.show()); }
} </java5>
2.5.2. (0.5 val.) Que padrão de desenho é usado no programa?
2.6. (2.5 val.) Desenhe o diagrama de classes UML correspondente ao seguinte problema:
Um empreiteiro da construção civil especializou-se na construção de vivendas e piscinas. Devido ao modo de construção modular, o negócio está a correr muito bem: existem muitas encomendas e os funcionários conseguem satisfazê-las a todas fazendo horas extraordinárias. Os operários (montam as vivendas e as piscinas) andam muito satisfeitos pois o vencimento mensal é função da antiguidade, do ordenado de base e das horas extraordinárias efectuadas. Os coordenadores de operários não recebem horas extraordinárias, mas recebem um prémio por cada vivenda ou piscina concluída. Os empregados do “backoffice” não recebem horas extraordinárias nem qualquer prémio.
As vivendas são construídas com base em módulos pré-fabricados: casas de banho, cozinhas, quartos, escadas e elevadores. Para equipar estas divisões, a empresa adquire sanitas, banheiras, lavatórios (usados nas casas de banho e nas cozinhas), candeeiros e interruptores.
Represente as classes pelos seus nomes, métodos e atributos. Indique também as relações de herança, associação e agregação.
2.7. (1.5 val.) Desenhe o diagrama de sequência UML correspondente à execução do programa da pergunta 2.5 (excepto as linhas marcadas com //!2.7
), incluindo as etapas de criação dos objectos. O diagrama de sequência deve conter os nomes das mensagens trocadas (não é necessário representar os argumentos dessas mensagens nem as correspondentes ao retorno).
2.8. (2.0 val.) Considere o seguinte problema. Uma loja mantém registos persistentes sobre os seus clientes: número de cliente, nome, contacto, data de nascimento e data da primeira compra. Mantém também um registo de cada compra que o cliente realizou ao longo tempo: data da compra, valor da compra, tipo de produto adquirido e modo de pagamento (dinheiro, cartão de débito, cartão de crédito bancário ou cartão de compras da loja). A loja dá prémios de fidelidade aos seus clientes, sob a forma de descontos. No final de cada ano, a loja precisa de produzir relatórios em função dos clientes. Assim, deve ser possível obter, com relativamente pouco esforço, diversas listas de clientes com base em critérios julgados interessantes (segmento etário, segmento por compras acumuladas, etc.). Concretize este problema em Java, definindo as classes que achar necessárias.
2.9. (2.0 val.) Altere (o menos possível) o programa abaixo para que seja mais simples adicionar formas de apresentação específicas a cada elemento de uma página. A nova implementação deve suportar novas adições de formas de apresentação com menos impacto que a apresentada: em particular, deveria ser possível acrescentar novas formas de apresentação sem alterar o código que obtiver. <java5> import java.util.ArrayList; abstract class Printable {
public abstract String show(); public void add(Printable p) { throw new UnsupportedOperationException(); }
}
class Paragraph extends Printable {
public String show() { return "[paragraph]"; }
}
class Image extends Printable {
public String show() { return "[image]"; }
}
class Album extends Printable {
public ArrayList<Printable> _printables = new ArrayList<Printable>(); public void add(Printable p) { _printables.add(p); } public String show() { String s = "["; for (Printable p: _printables) s += p.show(); s += "]"; return s; }
}
class Page extends Album {} class Book extends Album {} </java5>
1.1. Considere o diagrama UML (Figura 1, à direita). Qual das seguintes afirmações está correcta?
1.2. A definição de métodos, por uma classe, de métodos especificados numa interface, designa-se por:
1.3. Em Java, qual das seguintes frases está correcta?
1.4. A definição de uma classe por agregação de objectos de outras classes ou suas colecções designa-se por:
1.5. Em Java, a operação de serialização...
1.6. Em Java, relativamente à redefinição de métodos...
1.7. Em Java, uma classe anónima...
1.8. A utilização do padrão de desenho Façade...
1.9. O padrão de desenho Visitor...
1.10. O padrão de desenho Abstract Factory...
Aspectos importantes:
Exemplos:
Padrão comando: encapsulamento de operações como objectos.
Métodos a implementar nos comandos:
[[[paragraph][image]][[paragraph][image]]]
O padrão utilizado é o Composite (elementos "Printable").
Esboço do diagrama de classes para o problema apresentado (foram omitidas algumas setas para não sobrecarregar o diagrama: na resolução completa, deveriam ser incluídas).
Note-se que alguns objectos não indicam variáveis associadas (os resultados da criação desses objectos são imediatamente passados como argumentos de outros métodos).
Uso do padrão Visitor: uma classe de visita por forma de apresentação.
import java.util.ArrayList;
abstract class Printable {
public void add(Printable p) { throw new UnsupportedOperationException(); }
public abstract String accept(Printer v);
}
class Paragraph extends Printable {
public String accept(Printer v) { return v.showParagraph(this); }
}
class Image extends Printable {
public String accept(Printer v) { return v.showImage(this); }
}
class Album extends Printable {
public ArrayList<Printable> _printables = new ArrayList<Printable>();
public void add(Printable p) { _printables.add(p); }
public List<Printable> getPrintables() { return _printables; }
public String accept(Printer v) { return v.showAlbum(this); }
}
class Page extends Album {
public String accept(Printer v) { return v.showPage(this); }
}
class Book extends Album {
public String accept(Printer v) { return v.showBook(this); }
}
As formas de apresentação são as definidas pela hierarquia de visita abaixo: Printer
abstrai o conceito de apresentação; ShowWithBrackets
representa a forma de apresentação presente no código original. Novas formas de apresentação resumem-se à definição de classes como esta última e não implicam quaisquer alterações no restante código.
interface Printer {
String showParagraph(Paragraph p);
String showImage(Image i);
String showAlbum(Album a);
String showPage(Page p);
String showBook(Book b);
}
class ShowWithBrackets implements Printer {
public String showParagraph(Paragraph p) { return "[paragraph]"; }
public String showImage(Image i) { return "[image]"; }
public String showAlbum(Album a) {
String s = "[";
for (Printable p: a.getPrintables()) s += p.accept(this);
s += "]";
return s;
}
public String showPage(Page p) { return showAlbum(p); }
public String showBook(Book b) { return showAlbum(b); }
}
Note-se que se reutilizou a implementação para Album na apresentação de Page e de Book (tal como acontecia no código original).