Programação com Objectos/Teste de 2010/01/04

From Wiki**3

< Programação com Objectos

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 (definido em C) não pode ser chamado se o objecto for referenciado através do tipo B
  2. A fornece a C a implementação do método doThis definido pela interface I
  3. o método doIt pode ser invocado através de referências para A
  4. A é uma classe derivada de C
  5. A é uma classe derivada de B

1.2. Como se designa a implementação, numa classe, de vários métodos com o mesmo nome, mas com argumentos diferentes?

  1. polimorfismo
  2. herança
  3. serialização
  4. overriding
  5. overloading

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

  1. todas as classes são instâncias de java.lang.Class
  2. uma classe interna 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 não pode ser instanciada, mas pode definir construtores

1.4. Em Java, uma interface...

  1. apenas define assinaturas de métodos
  2. tem apenas membros públicos
  3. pode definir construtores, desde que sejam públicos
  4. não pode ser privada
  5. não pode conter classes internas

1.5. Em Java, uma excepção...

  1. tem de ser tratada, se for instância de uma subclasse de java.lang.RuntimeException
  2. não pode ser tratada, se for instância de uma subclasse de java.lang.RuntimeException
  3. pode ser lançada durante o tratamento de outra excepção
  4. é um mecanismo para uso exclusivo nas classes definidas pelo programador da aplicação
  5. se não for tratada explicitamente, é automaticamente tratada por java.lang.Object

1.6. Em Java, o método compareTo (definido quando se implementa java.lang.Comparable)...

  1. está automaticamente disponível em todas as classes
  2. é utilizado para definir ordem entre as instâncias de uma classe
  3. é utilizado pelas colecções para parametrizar algoritmos de ordenação
  4. é utilizado para determinar a classe de um objecto
  5. permite comparar dois objectos de qualquer tipo

1.7. Relativamente à interface java.util.Comparator, qual das seguintes frases está correcta?

  1. é um tipo primitivo
  2. as suas instâncias podem ser utilizadas para parametrizar algoritmos de ordenação
  3. uma classe deve implementá-la se se quiser que as suas instâncias sejam comparáveis
  4. só é relevante quando se usam instâncias de java.util.HashMap
  5. as respostas anteriores estão erradas

1.8. Ao utilizar o padrão de desenho Composite passa a ser possível...

  1. abstrair a criação de famílias de objectos relacionados
  2. adicionar responsabilidades a objectos individuais em tempo de execução
  3. representar uma operação a ser realizada sobre os elementos de uma estrutura de objectos
  4. gerir as dependências de outros objectos relativamente ao estado de um objecto
  5. tratar da mesma forma objectos individuais e suas agregações

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

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

  1. representa uma operação a ser realizada sobre os elementos de uma estrutura de objectos
  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.) Descreva em que medida o processo de redefinição de métodos aliado ao mecanismo de herança permite melhorar a escrita de programas.

2.2. (1.5 val.) Os padrões Façade e Bridge permitem abstrair funcionalidade existente através de conceitos que fazem uso dessa funcionalidade. Quais são os objectivos de cada um destes padrões de desenho. Acha que estes padrões de desenho são alternativos, i.e., um deles pode ser usado em alternativa ao outro? Dê um exemplo de utilização, onde se evidenciem as vantagens de cada um deles.

2.3. (1.5 val.) Diga o que entende por polimorfismo e descreva como é explorado no padrão Strategy. Apresente um exemplo de aplicação do padrão.

2.4. (1.0 val.) Considere o padrão de desenho Template Method. Descreva a estrutura prevista pelo padrão, assim como o modo de funcionamento. Quais são as vantagens da sua utilização? Dê um exemplo.

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)

public interface Predicate {
  boolean ok(int value);
}

public class GreaterThan implements Predicate {
  private int _value = 0;
  public GreaterThan(int value) { _value = value; }
  public boolean ok(int value) { return _value < value; }
}

public class EqualTo implements Predicate {
  private int _value = 0;
  public EqualTo(int value) { _value = value; }
  public boolean ok(int value) { return _value == value; }
}

public class DataStore {
  int _vector[] = { -1, 0, 1 };
  public boolean satisfies(Predicate predicate) {
    for (int value : _vector) {
      if (predicate.ok(value)) return true;
    }
    return false;
  }
}

public class Application {
  public static void main(String args[]) {
    DataStore ds = new DataStore();
    System.out.println(ds.satisfies(new EqualTo(-1)) ? "YES" : "NO");

    //!2.7 – ignorar a linha seguinte na resolução da questão 2.7
    System.out.println(ds.satisfies(new GreaterThan(2)) ? "YES" : "NO");
  }
}

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:

Uma empresa de mobiliário doméstico apostou numa gestão moderna onde os conceitos de estrutura leve e flexível foram aplicados. Assim a empresa não tem, nem meios de produção próprios, nem sistema de distribuição, nem sistema de contabilidade próprios, reduzindo os seus funcionários aos estritamente necessário: departamento de gestão e departamento de vendas. Os departamentos sub-contratados a empresas especializadas têm dois gestores dedicados.

Todo o mobiliário pode ser adquirido individualmente ou, por vezes, em grupos. Por exemplo, a mobília de quarto inclui uma cama, duas mesinhas de cabeceira, uma cómoda e dois tapetes.

Para facilitar a planificação do transporte, cada peça individual é caracterizada com o seu volume e o seu peso, para além do modelo (uma cadeia de caracteres) e do preço. O volume, peso e preço de qualquer grupo é calculado pelo somatório dos seus constituintes (sem qualquer desconto ou agravamento). Deve haver um método que permite calcular estes três atributos.

A empresa é caracterizada pelo seu capital social e pelos seus accionistas. Cada departamento não sub-contratado é caracterizado pelo número de funcionários e todos os departamentos são fornecedores de informação para que o departamento de gestão possa calcular o estado da empresa: saldo contabilístico e saldo financeiro (dep. contabilidade), volume de vendas (dep. vendas), custo de produção de uma peça e tempo para entrega (dep. produção) e número de peças vendidas (dep. distribuiçã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). 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 máquina de lavar tem um mecanismo que gere a abertura da porta, por forma a evitar acidentes com crianças. A máquina tem os seguintes botões e sensores: botão “ligar/desligar” (chama o método power); botão “abrir porta” (método open); sensor “porta fechada” (método closed). A máquina tem ainda um temporizador que emite um impulsos a cada segundo (por cada impulso é chamado o método tick). A máquina apenas pode ser ligada (botão “ligar/desligar”) se a porta estiver fechada: a máquina arranca e apenas pára quando o número de impulsos for igual a 5400 ou quando o botão “ligar/desligar” for premido, interrompendo a lavagem. Quer num caso, quer noutro, a máquina não permite abertura imediata da porta: é necessário esperar 120 impulsos para que a máquina reaja ao botão “abrir porta” (durante o tempo de espera, o botão “ligar/desligar” é ignorado). Caso a porta tenha sido fechada, mas não se tenha iniciado a lavagem, a abertura da porta é imediata. A máquina está inicialmente desligada e a porta está aberta. Represente a abertura da porta através da impressão de uma cadeia de caracteres.

Implemente todas as classes da máquina de lavar com controlador de segurança.

Chave da Parte 1

Figura 1

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

  1. doThat (definido em C) não pode ser chamado se o objecto for referenciado através do tipo B
  2. A fornece a C a implementação do método doThis definido pela interface I
  3. o método doIt pode ser invocado através de referências para A
  4. A é uma classe derivada de C
  5. A é uma classe derivada de B

1.2. Como se designa a implementação, numa classe, de vários métodos com o mesmo nome, mas com argumentos diferentes?

  1. polimorfismo
  2. herança
  3. serialização
  4. overriding
  5. overloading

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

  1. todas as classes são instâncias de java.lang.Class
  2. uma classe interna 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 não pode ser instanciada, mas pode definir construtores

1.4. Em Java, uma interface...

  1. apenas define assinaturas de métodos
  2. tem apenas membros públicos
  3. pode definir construtores, desde que sejam públicos
  4. não pode ser privada
  5. não pode conter classes internas

1.5. Em Java, uma excepção...

  1. tem de ser tratada, se for instância de uma subclasse de java.lang.RuntimeException
  2. não pode ser tratada, se for instância de uma subclasse de java.lang.RuntimeException
  3. pode ser lançada durante o tratamento de outra excepção
  4. é um mecanismo para uso exclusivo nas classes definidas pelo programador da aplicação
  5. se não for tratada explicitamente, é automaticamente tratada por java.lang.Object

1.6. Em Java, o método compareTo (definido quando se implementa java.lang.Comparable)...

  1. está automaticamente disponível em todas as classes
  2. é utilizado para definir ordem entre as instâncias de uma classe
  3. é utilizado pelas colecções para parametrizar algoritmos de ordenação
  4. é utilizado para determinar a classe de um objecto
  5. permite comparar dois objectos de qualquer tipo

1.7. Relativamente à interface java.util.Comparator, qual das seguintes frases está correcta?

  1. é um tipo primitivo
  2. as suas instâncias podem ser utilizadas para parametrizar algoritmos de ordenação
  3. uma classe deve implementá-la se se quiser que as suas instâncias sejam comparáveis
  4. só é relevante quando se usam instâncias de java.util.HashMap
  5. as respostas anteriores estão erradas

1.8. Ao utilizar o padrão de desenho Composite passa a ser possível...

  1. abstrair a criação de famílias de objectos relacionados
  2. adicionar responsabilidades a objectos individuais em tempo de execução
  3. representar uma operação a ser realizada sobre os elementos de uma estrutura de objectos
  4. gerir as dependências de outros objectos relativamente ao estado de um objecto
  5. tratar da mesma forma objectos individuais e suas agregações

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

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

  1. representa uma operação a ser realizada sobre os elementos de uma estrutura de objectos
  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. Overriding e Herança

Aspectos importantes:

  • Conceito e papel desempenhado pela redefinição de métodos (acesso a múltiplas implementações)
  • Conceito e papel desempenhado pela herança (fundamentalmente, acesso a métodos já definidos e polimorfismo de inclusão)
  • Emergência do polimorfismo

2.2. Façade & Bridge

Aspectos importantes:

  • Funcionamento do Façade
  • Funcionamento do Bridge
  • Embora ambos permitam definir uma (ou no caso do Bridge, mais de uma) interface sobre um conjunto de classes, no Bridge existe o aspecto de ser possível que tanto as classes de suporte, como as de abstração, poderem evoluir independentemente. No Façade, apenas se deseja um acesso mais simples e a coordenação de eventuais múltiplas invocações das classes por detrás da fachada.
  • Exemplos: Compilador (Façade -- simplificação de acesso à função principal); Interface gráfica (Bridge -- independência dos conceitos da interface, i.e., botões, janelas, etc., dos aspectos particulares de execução do desenho da interface).

2.3. Polimorfismo & Strategy

Aspectos importantes:

  • Polimorfismo, fundamentalmente o de inclusão (i.e., o que existe entre os tipos hierarquicamente relacionados, que permite a utilização de tipos mais genéricos de uma hierarquia para referenciar objectos de tipos mais específicos), mas também o paramétrico (e.g., utilizado para definição de classes cujo código pode ser tornado independente do tipo manipulador, e.g. ArrayList, etc.).
  • Strategy utiliza polimorfismo para permitir a escrita do algoritmo do cliente em função do tipo geral da estratégia, sendo possível utilizar a referência para apontar para instâncias das múltiplas (sub)classes que implementam as variantes do algoritmo.
  • Exemplo: algoritmos de ordenação (em que a estratégia de comparação é fornecida em tempo de chamada); algoritmos de selecção (selector encapsulado como objecto).

2.4. Template Method

Aspectos importantes:

  • Estrutura: uma superclasse que define um algoritmo que faz uso de funções eventualmente abstractas e que devem ser definidas pelas subclasses de forma a que possam satisfazer necessidades locais (o algoritmo -- template -- não é necessariamente reimplementado e é mantido para todas as subclasses).
  • Exemplo: preparação de bebida quente.

2.5.1. Saída do programa

YES\nNO\n

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

O padrão utilizado é o Strategy (predicado).

2.6. Diagrama de classes (UML)

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

PO-20100104-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-20100104-seq.png

2.8. Exercício de programação (Máquina de Lavar)

Usa-se o padrão State para controlo da porta da máquina.

A máquina é simples: contém as funções a desempenhar e que dependem do estado. Foram omitidos aspectos não importantes para o problema (i.e., como se fecha a porta e como se produzem os impulsos).

public class WashingMachine {
	/** Machine state. */
	private State _mode = new Open(this);

	/** closed sensor */
	public void closed() { _mode.closed(); }

	/** open button */
	public void open() { _mode.open();	}

	/** on/off button */
	public void power() { _mode.power(); }

	/** Timer (one tick per second). */
	public void tick() { _mode.tick(); }

	/**
	 * Switch mode. Note that this interface is public.
	 * @param mode the new mode.
	 */
	public void setState(State mode) {
		_mode = mode;
	}
}

A base de definição para os estado é como se indica de seguida. Contém, como se pode inferir da classe anterior, os métodos que dependem do estado da máquina (e que as subclasses de State codificam). Note-se que _machine foi definida como protected para simplificação da apresentação.

public abstract class State {
	/** The washing machine.	 */
	protected WashingMachine _machine;

	/** @param machine  is the washing machine. */
	public State(WashingMachine machine) { _machine = machine; }

	/** Behaviour for closing. */
	public abstract void closed();

	/** Behaviour for open. */
	public abstract void open();

	/** Behaviour for on/off. */
	public abstract void power();

	/** Behaviour for ticking. */
	public abstract void tick();
}

As subclasses definidas para o problema cobrem as seguintes situações: porta aberta (máquina necessariamente desligada); porta fechada (máquina não iniciou lavagem ou espera terminou); máquina a lavar (5400 impulsos ou interrupção via botão on/off); espera depois da lavagem (120 impulsos).

As mensagens são apresentadas apenas por claridade e não são necessárias (excepto onde indicado no enunciado).

Note-se ainda que seria possível factorizar o código de gestão dos impulsos.

public class Open extends State {
	/**
	 * @param machine
	 */
	public Open(WashingMachine machine) {
		super(machine);
		System.out.println("** OPEN MODE: reached.");
	}

	/**
	 * @see State#closed()
	 */
	@Override
	public void closed() {
		System.out.println("** OPEN MODE: closed sensor activated.");
		System.out.println("** OPEN MODE: switching to closed/idle mode.");
		_machine.setState(new ClosedIdle(_machine));
	}

	/**
	 * @see State#open()
	 */
	@Override
	public void open() {
		System.out.println("** OPEN MODE: open button pressed (ignored).");
	}

	/**
	 * @see Washing#power()
	 */
	@Override
	public void power() {
		System.out.println("** OPEN MODE: power button pressed (ignored).");
	}

	/**
	 * @see State#tick()
	 */
	@Override
	public void tick() {
		System.out.println("** OPEN MODE: tick received (ignored).");
	}
}
public class ClosedIdle extends State {
	/**
	 * @param machine
	 */
	public ClosedIdle(WashingMachine machine) {
		super(machine);
		System.out.println("** CLOSED/IDLE: reached.");
	}

	/**
	 * @see State#closed()
	 */
	@Override
	public void closed() {
		System.out.println("** CLOSED/IDLE MODE: closed sensor activated (ignored).");
	}

	/**
	 * @see State#open()
	 */
	@Override
	public void open() {
		System.out.println("** CLOSED/IDLE MODE: open button pressed.");
		System.out.println("** CLOSED/IDLE MODE: switching to open mode.");
		_machine.setState(new Open(_machine));
	}

	/**
	 * @see Washing#power()
	 */
	@Override
	public void power() {
		System.out.println("** CLOSED/IDLE MODE: power (on) button pressed.");
		System.out.println("** CLOSED/IDLE MODE: switching to washing mode.");
		_machine.setState(new Washing(_machine));
	}

	/**
	 * @see State#tick()
	 */
	@Override
	public void tick() {
		System.out.println("** CLOSED/IDLE MODE: tick received (ignored).");
	}
}
public class Washing extends State {
	/**
	 * Do not stay in this state after ticking this much.
	 */
	private int MAX_TICKS = 5400;
	
	/**
	 * How many ticks have we already counted?
	 */
	private int _ticks = 0;
	
	/**
	 * @param machine
	 */
	public Washing(WashingMachine machine) {
		super(machine);
		System.out.println("** WASHING MODE: reached.");
	}

	/**
	 * @see State#closed()
	 */
	@Override
	public void closed() {
		System.out.println("** WASHING MODE: closed sensor activated (ignored).");
	}

	/**
	 * @see State#open()
	 */
	@Override
	public void open() {
		System.out.println("** WASHING MODE: open button pressed (ignored).");
	}

	/**
	 * @see State#power()
	 */
	@Override
	public void power() {
		System.out.println("** WASHING MODE: power (off) button pressed.");
		System.out.println("** WASHING MODE: switching to wait mode.");
		_machine.setState(new Wait(_machine));
	}

	/**
	 * @see State#tick()
	 */
	@Override
	public void tick() {
		System.out.println("** WASHING MODE: tick: " + _ticks);
		_ticks++;
		if (_ticks >= MAX_TICKS) {
			System.out.println("** WASHING MODE: switching to wait mode.");
			_machine.setState(new Wait(_machine));
		}
	}
}
public class Wait extends State {
	/**
	 * Do not stay in this state after ticking this much.
	 */
	private int MAX_TICKS = 120;

	/**
	 * How many ticks have we already counted?
	 */
	private int _ticks = 0;

	/**
	 * @param machine
	 */
	public Wait(WashingMachine machine) {
		super(machine);
		System.out.println("** WAIT MODE: reached.");
	}

	/**
	 * @see State#closed()
	 */
	@Override
	public void closed() {
		System.out.println("** WAIT MODE: closed sensor activated (ignored).");
	}

	/**
	 * @see State#open()
	 */
	@Override
	public void open() {
		System.out.println("** WAIT MODE: open button pressed (ignored).");
	}

	/**
	 * @see Wait#power()
	 */
	@Override
	public void power() {
		System.out.println("** WAIT MODE: power button pressed (ignored).");
	}

	/**
	 * @see State#tick()
	 */
	@Override
	public void tick() {
		System.out.println("** WAIT MODE: tick: " + _ticks);
		_ticks++;
		if (_ticks >= MAX_TICKS) {
			System.out.println("** WAIT MODE: switching to idle mode.");
			_machine.setState(new ClosedIdle(_machine));
		}
	}
}