Difference between revisions of "Programação com Objectos/Teste de 2011/01/10"

From Wiki**3

< Programação com Objectos
(New page: {{TOCright}} == Parte 1 (resposta múltipla) == Figura 1 '''1.1.''' Considere o diagrama UML da figura 1 (à direita). Qual das seguintes ...)
 
Line 83: Line 83:
 
'''2.4.''' (1.5 val.) O padrão de desenho ''Visitor'' permite abstrair a aplicação de uma operação a uma estrutura de objectos. Diga qual é o princípio de funcionamento do padrão e que vantagens apresenta a sua utilização. Quais são os problemas introduzidos pela utilização do padrão? Dê um exemplo de aplicação.
 
'''2.4.''' (1.5 val.) O padrão de desenho ''Visitor'' permite abstrair a aplicação de uma operação a uma estrutura de objectos. Diga qual é o princípio de funcionamento do padrão e que vantagens apresenta a sua utilização. Quais são os problemas introduzidos pela utilização do padrão? Dê um exemplo de aplicação.
  
'''2.5.1.''' (1.0 val.) Que resultado se obtém quando se executa o seguinte programa? (represente mudanças de linha com \n)
+
'''2.5.''' Considere o seguinte programa em Java:
 
<java5>
 
<java5>
 
public abstract class Shell {
 
public abstract class Shell {
Line 136: Line 136:
 
}
 
}
 
</java5>
 
</java5>
 +
 +
'''2.5.1.''' (1.0 val.) Que resultado se obtém quando se executa o seguinte programa? (represente mudanças de linha com \n)
  
 
'''2.5.2.''' (0.5 val.) Que padrão de desenho é usado no programa?
 
'''2.5.2.''' (0.5 val.) Que padrão de desenho é usado no programa?
Line 141: Line 143:
 
'''2.5.3.''' (1.5 val.) Desenhe o diagrama de sequência UML correspondente à execução do programa, 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 de retorno; não é necessário explicitar o construtor de '''Shell''').
 
'''2.5.3.''' (1.5 val.) Desenhe o diagrama de sequência UML correspondente à execução do programa, 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 de retorno; não é necessário explicitar o construtor de '''Shell''').
  
'''2.6.''' (2.5 val.) Desenhe o diagrama de classes UML correspondente ao seguinte problema:
+
'''2.6.''' Considere o seguinte domínio:
 
 
Uma empresa especializou-se no fabrico de máquinas de lavar roupa e de máquinas de lavar loiça. A gestão é moderna, sendo as tarefas normalmente executadas pelos gestores (contratar funcionários, por exemplo) e distribuídas por todos os funcionários de forma rotativa. O conselho de gestão tem sempre um operário e um engenheiro.
 
 
 
As máquinas de lavar roupa desta empresa caracterizam-se pela sua segurança, por forma a evitar acidentes com crianças. A máquina de lavar roupa tem os seguintes botões e sensores: botão “ligar/desligar” (evento “press” chama o método “power”); botão “abrir porta” (evento “press” chama método “open”); sensor “porta fechada” (evento “trigger” chama método “closed”). A máquina tem ainda um temporizador, uma cuba rotativa e uma caixa metálica.
 
 
 
As máquinas de lavar loiça são muito semelhantes no hardware, sendo a principal diferença a ausência da cuba rotativa.
 
 
 
A empresa é caracterizada pelo seu capital social, pelo número de máquinas vendidas e pelo número de funcionários. Os funcionários são caracterizados pelo seu vencimento. As máquinas de lavar loiça pelo preço e peso. As máquinas de lavar roupa pelo preço, peso e pelo número de rotações da cuba (centrifugação).
 
 
 
Represente as classes (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, incluindo as etapas de criação dos objectos (ignore as linhas do programa assinaladas com //!2.7). O diagrama de sequência deve conter os nomes das mensagens trocadas (não é necessário representar os argumentos dessas mensagens nem as de retorno).
 
  
'''2.8.''' (2.0 val.) Uma agência de apoio humanitário organiza a sua actuação em função dos seus beneficiários: regiões, povoações e indivíduos (uma região contém povoações e as povoações contêm indivíduos). Cada tipo de beneficiário regista o nível de apoio recebido (um valor inteiro). Este valor é utilizado pela agência para determinar quais as regiões, as povoações, ou os indivíduos mais carenciados. A agência sabe que as condições/necessidades de ajuda variam com o período do ano e em função de catástrofes. Como tal, o processo de cálculo e actualização deve ser suficientemente flexível para poder ser alterado conforme as necessidades e deve ser independente dos beneficiários, para evitar introduzir mais complexidade nas suas vidas.
+
Uma biblioteca possui livros, CDs, vídeos e jogos. Todas estas obras são identificadas por um número de série, uma data de aquisição e uma descrição de catálogo. Os livros, CDs e vídeos têm ainda a indicação de qual é o título e de quem é o autor. Os vídeos e os jogos têm indicação de qual é a idade mínima para empréstimo. A biblioteca mantém sobre os seus visitantes um registo, no qual inclui (sobre cada um) o nome, a data de nascimento, morada e número de telefone. Quando é realizado um novo registo, o novo utilizador fica sem acesso às obras com idade controlada se a idade for menor que um valor dado (à medida que o tempo passa e o utilizador envelhece, o acesso vai também evoluindo). São definidos três níveis de acesso: infantil (>0), juvenil (>12) e adulto (>18). No caso de utilizadores não adultos, a biblioteca associa ao menor um utilizador adulto, que é responsável pelas obras emprestadas (mantém um registo dedicado às obras emprestadas ao menor). A biblioteca guarda um registo dos empréstimos realizados (obra emprestada, utilizador e datas de empréstimo e limite para entrega). É possível pedir várias obras num único empréstimo e é possível contabilizar, tanto por utilizador, como na totalidade dos utilizadores, o número de obras emprestadas. Se uma obra não estiver disponível, é possível deixar um contacto para notificação em caso de devolução.
  
Considerando o exposto acima, a agência define um calculador de benefícios (designado genericamente por Calculator). A implementação mais simples (designada por Standard) contabiliza: para cada indivíduo, uma unidade de ajuda; para cada povoação, o somatório das ajudas aos indivíduos que a habitam; e, para cada região, o somatório dos valores da ajuda dadas às povoações que contém. Existe ainda o calculador para casos de catástrofe (designado por Emergency), que difere do Standard por contabilizar menos ajuda (apenas 75% do total) para povoações com mais de 100 indivíduos e menos ajuda (apenas 90% do total) para regiões com mais de 20 povoações.
+
'''2.6.1.''' (2.0 val.) Desenhe o diagrama de classes UML correspondente ao domínio apresentado. Represente as classes (seus nomes, métodos e atributos). Indique também as relações de herança, associação e agregação.
  
Implemente todos os conceitos. Considere que deve ser possível definir novas formas de cálculo sem necessitar alterar, nem os indivíduos, nem as povoações, nem as regiões.
+
'''2.6.2.''' (4.0 val.) Implemente em Java todas as classes, bem como os seus atributos e métodos, do domínio apresentado. Considere que deve haver flexibilidade na definição do tipo de cliente, na forma de transitar entre tipos de cliente, e no registo de empréstimos.
  
 
== Chave da Parte 1 ==
 
== Chave da Parte 1 ==
Line 165: Line 155:
 
[[Image:UML-teste-po-20100121.png|frame|right| Figura 1]]
 
[[Image:UML-teste-po-20100121.png|frame|right| Figura 1]]
 
'''1.1.''' Considere o diagrama UML da figura 1 (à direita). Qual das seguintes afirmações está correcta?
 
'''1.1.''' Considere o diagrama UML da figura 1 (à direita). Qual das seguintes afirmações está correcta?
:#<s>doThat (definido em C) não pode ser chamado se o objecto for referenciado através do tipo B</s>
+
:#<s>doThat pode ser invocado através de referências para I</s>
:#<s>B implementa I através de C</s>
+
:#<s>doThat não está definido para B</s>
:#o método doIt pode ser invocado através de referências para C
+
:#doIt pode ser invocado através de referências para C
:#<s>os métodos de A não podem ser invocados sobre instâncias de C</s>
+
:#<s>A implementa I</s>
:#<s>A é uma classe derivada de B</s>
+
:#<s>A é uma classe derivada de C</s>
  
'''1.2.''' Como se designa a operação que permite que um tipo hierarquicamente superior seja usado para referir uma instância de um tipo dele derivado?
+
'''1.2.''' Que padrão de desenho permite especificar numa classe o esqueleto de um algoritmo, deixando para as subclasses a concretização dos seus passos?
:#<s>polimorfismo</s>
+
:#<s>Strategy</s>
:#<s>herança</s>
+
:#<s>Bridge</s>
:#upcasting
+
:#Template Method
:#<s>downcasting</s>
+
:#<s>Visitor</s>
:#<s>redefinição</s>
+
:#<s>State</s>
  
'''1.3.''' Em Java, qual das seguintes frases está incorrecta?
+
'''1.3.''' Em Java, qual das seguintes frases está correcta?
:#<s>java.lang.Object pode referir qualquer objecto</s>
+
:#<s>todas as classes são derivadas de java.lang.Class</s>
:#<s>uma classe anónima pode implementar uma interface</s>
+
:#<s>uma classe interna não pode ser anónima</s>
:#<s>uma classe abstracta pode sempre definir construtores</s>
+
:#uma classe anónima pode implementar uma interface
:#<s>java.util.Collection é uma especialização de java.util.Iterable</s>
+
:#<s>java.lang.Object contém os métodos que permitem definir a ordem por omissão entre quaisquer objectos</s>
:#java.lang.Serializable declara os métodos que permitem escrever um objecto para um canal de saída
+
:#<s>uma classe abstracta pode ser instanciada se definir construtores</s>
  
'''1.4.''' Em Java, uma classe anónima...
+
'''1.4.''' Em Java, um construtor...
:#<s>apenas define assinaturas de métodos</s>
+
:#<s>não pode chamar outros construtores</s>
:#pode ter membros não públicos
+
:#<s>não pode chamar funções static</s>
:#<s>não pode ter membros privados</s>
+
:#chama sempre o construtor da superclasse
:#<s>não pode ser instanciada</s>
+
:#<s>não pode ser privado</s>
:#<s>não pode implementar uma interface</s>
+
:#<s>não pode declarar variáveis locais</s>
  
'''1.5.''' Em Java, a classe java.io.Reader...
+
'''1.5.''' Em Java, as classes internas...
:#<s>permite ler objectos “serializados” (i.e., instâncias de classes que implementem java.io.Serializable)</s>
+
:#<s>não podem ser serializáveis (i.e., não podem implementar java.io.Serializable)</s>
:#permite ler caracteres (texto)
+
:#<s>não podem conter métodos que lancem excepções</s>
:#<s>permite ler bytes (dados binários)</s>
+
:#podem ser instanciadas dentro de qualquer bloco de uma função
:#<s>não pode ser utilizada como tipo de atributos de outras classes</s>
+
:#<s>constituem um mecanismo para uso exclusivo do tratamento de excepções</s>
:#<s>é um tipo primitivo</s>
+
:#<s>não podem ter métodos públicos</s>
  
'''1.6.''' Em Java, o parâmetro E em java.util.Iterable<E>...
+
'''1.6.''' Em Java, o método equals...
:#<s>é uma constante que especifica o limite superior para a iteração</s>
+
:#<s>não está disponível nas classes da package java.util</s>
:#<s>é utilizado para definir o passo de iteração (i.e., quantos elementos se deve saltar – por omissão, é 1)</s>
+
:#<s>é utilizado para definir ordem entre as instâncias de uma classe</s>
:#<s>permite especificar o tipo do comparador de elementos (instância referida por java.util.Comparator<E>)</s>
+
:#<s>está disponível apenas para classes que implementem  java.io.Serializable</s>
:#define tipo retornado pelo iterador correspondente
+
:#<s>permite comparar apenas objectos com outros da mesma classe</s>
:#<s>não deve ser usado</s>
+
:#permite comparar dois objectos de qualquer tipo
  
'''1.7.''' Relativamente à interface java.util.Iterator, qual das seguintes frases está correcta?
+
'''1.7.''' Em Java, a interface java.lang.Comparable ...
:#<s>quando associado à interface de java.lang.Object, permite percorrer qualquer objecto</s>
+
:#<s>é implementada pela classe java.lang.Object</s>
:#<s>sendo uma interface para iteração, não pode ser implementada por qualquer classe</s>
+
:#as instâncias das suas implementações podem ser utilizadas como chaves pela classe java.util.TreeMap
:#permite a definição de algoritmos abstractos baseados em iteração
+
:#<s>uma classe não deve implementá-la se quiser que as suas instâncias sejam serializáveis</s>
:#<s>só é relevante quando se usam instâncias referenciáveis por java.util.Collection</s>
+
:#<s>só é relevante para classes que implementem java.util.List</s>
:#<s>define a política de comparação de elementos de uma colecção</s>
+
:#<s>as respostas anteriores estão erradas</s>
  
'''1.8.''' O padrão de desenho State...
+
'''1.8.''' Relativamente aos padrões de desenho State e Strategy...
:#<s>permite delegar comportamentos específicos em objectos que os encapsulam</s>
+
:#ambos especificam a delegação de acções em objectos usados pelo cliente
:#<s>permite adicionar responsabilidades a objectos individuais em tempo de execução</s>
+
:#<s>as estratégias têm de ser fixadas na altura da criação do cliente, mas os estados não</s>
:#permite delegar comportamentos dependentes do estado de um objecto
+
:#<s>são idênticos, mas as classes que implementam as estratégias são em número fixo</s>
:#<s>permite gerir as dependências de outros objectos relativamente ao estado de um objecto</s>
+
:#<s>gerem as dependências de objectos das suas implementações</s>
:#<s>permite guardar o estado de um objecto num canal de saída, para posterior recuperação</s>
+
:#<s>tratam da mesma forma objectos individuais e suas agregações</s>
  
'''1.9.''' O padrão de desenho Template Method...
+
'''1.9.''' O padrão de desenho Decorator...
:#<s>permite adicionar funcionalidade a um objecto sem alterar a sua interface</s>
+
:#permite adicionar funcionalidade a um objecto sem alterar a sua interface
:#<s>deve ser utilizado quando o uso do mecanismo de herança não for conveniente</s>
+
:#<s>não pode ser aplicado em conjunto com padrão Visitor</s>
 
:#<s>permite ajustar a interface e o comportamento de um objecto</s>
 
:#<s>permite ajustar a interface e o comportamento de um objecto</s>
:#<s>define uma operação a aplicar a uma estrutura de objectos</s>
+
:#<s>permite aplicar uma operação a uma estrutura de objectos</s>
:#estabelece que uma classe defina um algoritmo cujas partes devem ser implementadas pela subclasses
+
:#<s>permite estabelecer o esqueleto de um algoritmo</s>
  
'''1.10.''' O padrão de desenho Observer...
+
'''1.10.''' O padrão de desenho Abstract Factory...
:#<s>representa uma operação a ser realizada sobre os elementos de uma estrutura de objectos</s>
+
:#<s>representa a construção de uma colecção</s>
:#permite gerir as dependências de outros objectos relativamente ao estado de um objecto
+
:#<s>gerir as dependências de outros objectos relativamente ao estado de um objecto</s>
:#<s>permite abstrair o uso de grupos de objectos por uma aplicação</s>
+
:#permite abstrair a criação de famílias de objectos para uma aplicação
 
:#<s>permite tratar famílias de objectos e seus grupos indiscriminadamente</s>
 
:#<s>permite tratar famílias de objectos e seus grupos indiscriminadamente</s>
 
:#<s>permite que o comportamento de um objecto mude quando o seu estado muda</s>
 
:#<s>permite que o comportamento de um objecto mude quando o seu estado muda</s>

Revision as of 13:50, 17 January 2011

Parte 1 (resposta múltipla)

Figura 1

1.1. Considere o diagrama UML da figura 1 (à direita). Qual das seguintes afirmações está correcta?

  1. doThat pode ser invocado através de referências para I
  2. doThat não está definido para B
  3. doIt pode ser invocado através de referências para C
  4. A implementa I
  5. A é uma classe derivada de C

1.2. Que padrão de desenho permite especificar numa classe o esqueleto de um algoritmo, deixando para as subclasses a concretização dos seus passos?

  1. Strategy
  2. Bridge
  3. Template Method
  4. Visitor
  5. State

1.3. Em Java, qual das seguintes frases está correcta?

  1. todas as classes são derivadas de java.lang.Class
  2. uma classe interna não pode ser anónima
  3. uma classe anónima pode implementar uma interface
  4. java.lang.Object contém os métodos que permitem definir a ordem por omissão entre quaisquer objectos
  5. uma classe abstracta pode ser instanciada se definir construtores

1.4. Em Java, um construtor...

  1. não pode chamar outros construtores
  2. não pode chamar funções static
  3. chama sempre o construtor da superclasse
  4. não pode ser privado
  5. não pode declarar variáveis locais

1.5. Em Java, as classes internas...

  1. não podem ser serializáveis (i.e., não podem implementar java.io.Serializable)
  2. não podem conter métodos que lancem excepções
  3. podem ser instanciadas dentro de qualquer bloco de uma função
  4. constituem um mecanismo para uso exclusivo do tratamento de excepções
  5. não podem ter métodos públicos

1.6. Em Java, o método equals...

  1. não está disponível nas classes da package java.util
  2. é utilizado para definir ordem entre as instâncias de uma classe
  3. está disponível apenas para classes que implementem java.io.Serializable
  4. permite comparar apenas objectos com outros da mesma classe
  5. permite comparar dois objectos de qualquer tipo

1.7. Em Java, a interface java.lang.Comparable ...

  1. é implementada pela classe java.lang.Object
  2. as instâncias das suas implementações podem ser utilizadas como chaves pela classe java.util.TreeMap
  3. uma classe não deve implementá-la se quiser que as suas instâncias sejam serializáveis
  4. só é relevante para classes que implementem java.util.List
  5. as respostas anteriores estão erradas

1.8. Relativamente aos padrões de desenho State e Strategy...

  1. ambos especificam a delegação de acções em objectos usados pelo cliente
  2. as estratégias têm de ser fixadas na altura da criação do cliente, mas os estados não
  3. são idênticos, mas as classes que implementam as estratégias são em número fixo
  4. gerem as dependências de objectos das suas implementações
  5. tratam da mesma forma objectos individuais e suas agregações

1.9. O padrão de desenho Decorator...

  1. permite adicionar funcionalidade a um objecto sem alterar a sua interface
  2. não pode ser aplicado em conjunto com padrão Visitor
  3. permite ajustar a interface e o comportamento de um objecto
  4. permite aplicar uma operação a uma estrutura de objectos
  5. permite estabelecer o esqueleto de um algoritmo

1.10. O padrão de desenho Abstract Factory...

  1. representa a construção de uma colecção
  2. gerir as dependências de outros objectos relativamente ao estado de um objecto
  3. permite abstrair a criação de famílias de objectos para uma aplicação
  4. permite tratar famílias de objectos e seus grupos indiscriminadamente
  5. permite que o comportamento de um objecto mude quando o seu estado muda

Parte 2

2.1. (1.5 val.) Na linguagem Smalltalk, o método subclassResponsibility pode ser invocado por uma superclasse para indicar que a implementação de um determinado método é da responsabilidade de uma subclasse. Desse modo, se for usada uma subclasse que não implemente o método, o programa chama a versão da superclasse e recebe uma notificação da falta durante a execução. Qual é o mecanismo discutido acima e como é disponibilizado na linguagem Java? Diga quais são as suas vantagens relativas.

2.2. (1.5 val.) O mecanismo de herança potencia o desenvolvimento incremental e a reutilização de funcionalidade existente. No entanto, apesar destes aspectos positivos, apresenta algumas limitações. Descreva algumas das limitações do mecanismo de herança (pode particularizar para Java) e em que medida a utilização de arquitecturas como as previstas em alguns padrões de desenho as minimizam.

2.3. (1.5 val.) Descreva o padrão de desenho State e as vantagens da sua utilização. Explique em que medida o mecanismo de polimorfismo de inclusão é importante para a definição e funcionamento da arquitectura prevista pelo padrão. Dê um exemplo de utilização do padrão.

2.4. (1.5 val.) O padrão de desenho Visitor permite abstrair a aplicação de uma operação a uma estrutura de objectos. Diga qual é o princípio de funcionamento do padrão e que vantagens apresenta a sua utilização. Quais são os problemas introduzidos pela utilização do padrão? Dê um exemplo de aplicação.

2.5. Considere o seguinte programa em Java: <java5> public abstract class Shell {

 protected Ghost _ghost;
 protected Shell(Ghost ghost) { 
   _ghost = ghost;
   System.out.println(getClass().getName());
 }
 public abstract boolean isOperational();
 public abstract void powerOn();

}

public class Virtual extends Shell {

 public Virtual(Ghost ghost) { super(ghost); }
 public boolean isOperational() { return _ghost.isHappy(); }
 public void powerOn() { System.out.println("always on: nothing to do"); }

}

public class Physical extends Shell {

 private boolean _poweredOn = false;
 public Physical(Ghost ghost) { super(ghost); powerOn(); }
 public boolean isOperational() { return _poweredOn && _ghost.isHappy(); }
 public void powerOn() { _poweredOn = true; }

}

public class NotReadyException extends Exception {}

public class ShellTester {

 public void assertOperational(Shell shell) throws NotReadyException {
   if (!shell.isOperational()) {
     throw new NotReadyException();
   }
 }

}

public class Ghost {

 String _name;
 public Ghost(String name) { _name = name; }
 public boolean isHappy() { return true; /* ghosts are happy */ }

}

public class Application {

 public static void main(String args[]) {
   Shell kusanagi = new Virtual(new Ghost("草薙素子"));
   Shell batou = new Physical(new Ghost("バトー"));
   ShellTester tester = new ShellTester();
   try { tester.assertOperational(kusanagi); }
   catch (NotReadyException e) { System.out.println("Kusanagi not ready!"); }
   try { tester.assertOperational(batou); }
   catch (NotReadyException e) { System.out.println("Batou not ready!"); }
 }

} </java5>

2.5.1. (1.0 val.) Que resultado se obtém quando se executa o seguinte programa? (represente mudanças de linha com \n)

2.5.2. (0.5 val.) Que padrão de desenho é usado no programa?

2.5.3. (1.5 val.) Desenhe o diagrama de sequência UML correspondente à execução do programa, 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 de retorno; não é necessário explicitar o construtor de Shell).

2.6. Considere o seguinte domínio:

Uma biblioteca possui livros, CDs, vídeos e jogos. Todas estas obras são identificadas por um número de série, uma data de aquisição e uma descrição de catálogo. Os livros, CDs e vídeos têm ainda a indicação de qual é o título e de quem é o autor. Os vídeos e os jogos têm indicação de qual é a idade mínima para empréstimo. A biblioteca mantém sobre os seus visitantes um registo, no qual inclui (sobre cada um) o nome, a data de nascimento, morada e número de telefone. Quando é realizado um novo registo, o novo utilizador fica sem acesso às obras com idade controlada se a idade for menor que um valor dado (à medida que o tempo passa e o utilizador envelhece, o acesso vai também evoluindo). São definidos três níveis de acesso: infantil (>0), juvenil (>12) e adulto (>18). No caso de utilizadores não adultos, a biblioteca associa ao menor um utilizador adulto, que é responsável pelas obras emprestadas (mantém um registo dedicado às obras emprestadas ao menor). A biblioteca guarda um registo dos empréstimos realizados (obra emprestada, utilizador e datas de empréstimo e limite para entrega). É possível pedir várias obras num único empréstimo e é possível contabilizar, tanto por utilizador, como na totalidade dos utilizadores, o número de obras emprestadas. Se uma obra não estiver disponível, é possível deixar um contacto para notificação em caso de devolução.

2.6.1. (2.0 val.) Desenhe o diagrama de classes UML correspondente ao domínio apresentado. Represente as classes (seus nomes, métodos e atributos). Indique também as relações de herança, associação e agregação.

2.6.2. (4.0 val.) Implemente em Java todas as classes, bem como os seus atributos e métodos, do domínio apresentado. Considere que deve haver flexibilidade na definição do tipo de cliente, na forma de transitar entre tipos de cliente, e no registo de empréstimos.

Chave da Parte 1

Figura 1

1.1. Considere o diagrama UML da figura 1 (à direita). Qual das seguintes afirmações está correcta?

  1. doThat pode ser invocado através de referências para I
  2. doThat não está definido para B
  3. doIt pode ser invocado através de referências para C
  4. A implementa I
  5. A é uma classe derivada de C

1.2. Que padrão de desenho permite especificar numa classe o esqueleto de um algoritmo, deixando para as subclasses a concretização dos seus passos?

  1. Strategy
  2. Bridge
  3. Template Method
  4. Visitor
  5. State

1.3. Em Java, qual das seguintes frases está correcta?

  1. todas as classes são derivadas de java.lang.Class
  2. uma classe interna não pode ser anónima
  3. uma classe anónima pode implementar uma interface
  4. java.lang.Object contém os métodos que permitem definir a ordem por omissão entre quaisquer objectos
  5. uma classe abstracta pode ser instanciada se definir construtores

1.4. Em Java, um construtor...

  1. não pode chamar outros construtores
  2. não pode chamar funções static
  3. chama sempre o construtor da superclasse
  4. não pode ser privado
  5. não pode declarar variáveis locais

1.5. Em Java, as classes internas...

  1. não podem ser serializáveis (i.e., não podem implementar java.io.Serializable)
  2. não podem conter métodos que lancem excepções
  3. podem ser instanciadas dentro de qualquer bloco de uma função
  4. constituem um mecanismo para uso exclusivo do tratamento de excepções
  5. não podem ter métodos públicos

1.6. Em Java, o método equals...

  1. não está disponível nas classes da package java.util
  2. é utilizado para definir ordem entre as instâncias de uma classe
  3. está disponível apenas para classes que implementem java.io.Serializable
  4. permite comparar apenas objectos com outros da mesma classe
  5. permite comparar dois objectos de qualquer tipo

1.7. Em Java, a interface java.lang.Comparable ...

  1. é implementada pela classe java.lang.Object
  2. as instâncias das suas implementações podem ser utilizadas como chaves pela classe java.util.TreeMap
  3. uma classe não deve implementá-la se quiser que as suas instâncias sejam serializáveis
  4. só é relevante para classes que implementem java.util.List
  5. as respostas anteriores estão erradas

1.8. Relativamente aos padrões de desenho State e Strategy...

  1. ambos especificam a delegação de acções em objectos usados pelo cliente
  2. as estratégias têm de ser fixadas na altura da criação do cliente, mas os estados não
  3. são idênticos, mas as classes que implementam as estratégias são em número fixo
  4. gerem as dependências de objectos das suas implementações
  5. tratam da mesma forma objectos individuais e suas agregações

1.9. O padrão de desenho Decorator...

  1. permite adicionar funcionalidade a um objecto sem alterar a sua interface
  2. não pode ser aplicado em conjunto com padrão Visitor
  3. permite ajustar a interface e o comportamento de um objecto
  4. permite aplicar uma operação a uma estrutura de objectos
  5. permite estabelecer o esqueleto de um algoritmo

1.10. O padrão de desenho Abstract Factory...

  1. representa a construção de uma colecção
  2. gerir as dependências de outros objectos relativamente ao estado de um objecto
  3. permite abstrair a criação de famílias de objectos para uma aplicação
  4. permite tratar famílias de objectos e seus grupos indiscriminadamente
  5. permite que o comportamento de um objecto mude quando o seu estado muda

Resolução da Parte 2

2.1. Classes Paramétricas e Polimorfismo

Aspectos importantes:

  • Definição de uma classe estruturalmente independente do(s) tipo(s) manipulado(s) (os seus parâmetros).
  • O polimorfismo implicado pelas relações de herança (inclusão) permite o uso de uma instância de uma subclasse onde se espera uma de uma superclasse. O polimorfismo paramétrico permite a definição de classes concretas que manipulam qualquer tipo (potencialmente com restrições), evitando a definição de relações de herança (dependência) relativamente a um tipo determinado (introduz restrições desnecessárias). Note-se que uma classe paramétrica pode participar em relações de herança/implementação e ser usada polimorficamente (inclusão) como qualquer outra (e.g., List<A> e ArrayList<A>). No entanto, casos como ArrayList<Animal> e ArrayList<Gato> não estão relacionadas polimorficamente.

2.2. Visitor & Strategy

Aspectos importantes:

  • Descrição da estrutura e funcionamento do Visitor
  • Vantagens e inconvenientes
  • Exemplos: geração de código num compilador a partir de uma árvore sintáctica; desenho de uma cena a partir de uma descrição abstracta; cálculo de impostos sobre uma estrutura composta. Em geral, situações em que uma operação a realizar sobre uma estrutura de objectos e suas folhas possa ser generalizada.
  • Visitor vs. Strategy: embora ambos os padrões permitam encapsular algoritmos a realizar sobre estruturas "clientes", tanto a estrutura como o modo de funcionamento são diferentes. No Strategy, apesar de ser possível definir múltiplas versões de um algoritmo, não é possível especializar a operação dependendo do tipo específico do objecto.

2.3. Abstract Factory

Aspectos importantes:

  • Descrição da estrutura e funcionamento do Abstract Factory
  • Abstract Factory utiliza polimorfismo para permitir o intercâmbio de fábricas sem ser necessário alterar a aplicação cliente
  • Exemplo: escola com professores, salas, alunos, etc.: a estrutura da escola é sempre a mesma, mas a parametrização definida pela fábrica altera o funcionamento (por produzir intervenientes diferentes)

2.4. Composite

Aspectos importantes:

  • Estrutura: uma superclasse define o conceito abstracto a manipular. As subclasses, tanto atómicas, como as composições de componentes, são tratadas indistintamente e apresentam a mesma interface. O processamento de uma composição faz-se pelo processamento iterativo dos seus elementos.
  • Exemplo: Rebanhos e Ovelhas (relativamente, por exemplo, à operação tosquiar).

2.5.1. Saída do programa

A\nC\nB\nA\nC\n

2.5.2. Identificação do padrão de desenho utilizado

O padrão utilizado é o State (Ghost).

2.6. Diagrama de classes (UML)

Esboço do diagrama de classes para o problema apresentado.

PO-20100121-class.png

2.7. Diagrama de sequência (UML)

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).

PO-20100121-seq.png

2.8. Exercício de programação (Apoio Humanitário)

Usa-se o padrão Visitor como forma de abstrair o cálculo da ajuda prestada.

Definem-se quatro conceitos: o beneficiário abstracto (HelpTarget), e cada um dos concretos (Person, Village, Region).

<java5> /**

* Basic help target.
*/

public abstract class HelpTarget {

       /**
        * No actual value is returned in this case.
        *
        * @param calculator the visitor used to evaluate assistance.
        * @return help received by this target.
        */
       public double accept(Calculator calculator) { throw new UnsupportedOperationException(); }

} </java5>

<java5> /**

* Individual.
* We omitted the initialisation code.
*/

public class Person extends HelpTarget {

       /**
        * @see HelpTarget#accept(Calculator)
        */
       @Override
       public double accept(Calculator calculator) { return calculator.evalPerson(this); }

}

</java5>

<java5> import java.util.ArrayList;

/**

* A village has villagers (persons).
* We omitted the initialisation code.
*/

public class Village extends HelpTarget {

       /**
        * The villagers in this village.
        */
       private ArrayList<Person> _villagers = new ArrayList<Person>();
       /**
        * Simple constructor for initialising the village with some villagers.
        */
       public Village() {
               int count = (int) (Math.random() * 100);
               for (int i = 0; i < count; i++) _villagers.add(new Person());
       }
       /**
        * @return size of village (number of villagers).
        */
       public int size() { return _villagers.size(); }
       /**
        * @param index
        * @return a villager
        */
       public Person getVillager(int index) { return _villagers.get(index); }
       /**
        * @see HelpTarget#accept(Calculator)
        */
       @Override
       public double accept(Calculator calculator) { return calculator.evalVillage(this); }

} </java5>

<java5> import java.util.ArrayList;

/**

* A region has villages.
* We omitted the initialisation code.
*/

public class Region extends HelpTarget {

       /**
        * The villages in this region.
        */
       private ArrayList<Village> _villages = new ArrayList<Village>();
       /**
        * Simple constructor for initialising the region with some villages.
        */
       public Region() {
               int count = (int) (Math.random() * 100);
               for (int i = 0; i < count; i++) _villages.add(new Village());
       }
       /**
        * @return size of region (number of villages).
        */
       public int size() {return _villages.size(); }
       /**
        * @param index
        * @return a village
        */
       public Village getVillage(int index) { return _villages.get(index); }
       /**
        * @see HelpTarget#accept(Calculator)
        */
       @Override
       public double accept(Calculator calculator) { return calculator.evalRegion(this); }

} </java5>

A classe Calculator define a interface de cálculo para cada conceito. <java5> /**

* The Calculator visitor interface.
*/

public abstract class Calculator {

       /**
        * @param person
        * @return help received by this person.
        */
       public abstract double evalPerson(Person person);
       /**
        * @param village
        * @return help received by this village.
        */
       public abstract double evalVillage(Village village);
       /**
        * @param region
        * @return help received by this region.
        */
       public abstract double evalRegion(Region region);

} </java5>

O processo de cálculo simples é definido pela classe Standard.

<java5> /**

* "Standard" help calculator.
*/

public class Standard extends Calculator {

       /**
        * @see Calculator#evalVillage(Village)
        */
       @Override
       public double evalVillage(Village village) {
               double tax = 0;
               for (int index = 0; index < village.size(); index++)
                       tax += village.getVillager(index).accept(this);
               return tax;
       }
       /**
        * @see Calculator#evalPerson(Person)
        */
       @Override
       public double evalPerson(Person person) {
               return 1;
       }
       /**
        * @see Calculator#evalRegion(Region)
        */
       @Override
       public double evalRegion(Region region) {
               double tax = 0;
               for (int index = 0; index < region.size(); index++)
                       tax += region.getVillage(index).accept(this);
               return tax;
       }

} </java5>

O processo de cálculo para emergências é definido pela classe Emergency.

<java5> /**

* The emergency help system.
*/

public class Emergency extends Calculator {

       /**
        * High-water marker for region occupation.
        */
       private final int REGION_MAX = 20;
       /**
        * High-water marker for population.
        */
       private final int VILLAGE_MAX = 100;
       /**
        * @see Calculator#evalVillage(Village)
        */
       @Override
       public double evalVillage(Village village) {
               double help = 0;
               for (int index = 0; index < village.size(); index++)
                       help += village.getVillager(index).accept(this);
               if (village.size() > VILLAGE_MAX) help *= .75;
               return help;
       }

       /**
        * @see Calculator#evalPerson(Person)
        */
       @Override
       public double evalPerson(Person person) { return 1; }

       /**
        * @see Calculator#evalRegion(Region)
        */
       @Override
       public double evalRegion(Region region) {
               double help = 0;
               for (int index = 0; index < region.size(); index++)
                       help += region.getVillage(index).accept(this);
               if (region.size() > REGION_MAX) help *= .9;
               return help;
       }

} </java5>

Simple aoolication.

<java5> public class App {

       /**
        * @param args
        */
       public static void main(String[] args) {
               HelpTarget v1 = new Village();
               HelpTarget r1 = new Region();
               HelpTarget p1 = new Person();

               Calculator sh = new Standard();
               Calculator eh = new Emergency();

               System.out.println("Village help (standard): " + v1.accept(sh));
               System.out.println("Region taxes (standard): " + r1.accept(sh));
               System.out.println("Person taxes (standard): " + p1.accept(sh));
               System.out.println("Village taxes (emergency): " + v1.accept(eh));
               System.out.println("Region taxes (emergency): " + r1.accept(eh));
               System.out.println("Person taxes (emergency): " + p1.accept(eh));
       }

} </java5>