Aula Prática 11 · Programação com Objectos
Aplicação de padrões de desenho: Singleton, Composite, Strategy, Template Method, Decorator, Factory Method
Resolução do exercício EP8 para avaliação
Considere a seguinte classe, que representa uma ligação a uma base de dados e é responsável por enviar as interrogações feitas por clientes desta classe a um sistema relacional de bases de dados e por devolver o resultado das interrogações:
// creates a connection to a relational dataabse system
public DatabaseConnection() {
// code for initializing state of this object
// and establishing a connection with the database server
public ResultSet executeQuery(String sqlQuery) {
// executes the query and returns the answer
Neste exemplo de código, sempre que criar um novo objecto desta classe vai-se criar uma ligação ao servidor de base de dados. Se forem criadas várias instâncias na mesma aplicação, vão ser criadas múltiplas (idênticas) ligações à base de dados.
Qual o padrão de desenho a utilizar para garantir que apenas se tem no máximo uma única instância de DatabaseConnection e que esta instância apenas é criada quando realmente for necessária.?
Altere o código desta classe aplicando o padrão escolhido.
Considere o seguinte domínio.
Uma empresa de consultoria na área de desenvolvimento de software realiza assistência a projectos de desenvolvimento de software . A empresa de consultoria tem empregados: gestores, programadores normais e programadores peritos. Cada empregado realiza um tipo de trabalho específico, o gestor gere um projecto, o programador normal programa e o programador perito programa muito. Adicionalmente, cada tipo de trabalhador tem um custo distinto: o gestor custa 1000 euros, o programador normal custa 1500 euros e o programador perito custa 10000 euros.
No contexto de um projecto, a empresa de consultoria pode atribuir o projecto a um dos seus empregados ou pode constituir uma equipa com vários dos seus empregados (podendo ainda agrupar os empregados em sub-equipas) e atribuir a equipa ao projecto. O custo do projecto depende do custo dos empregados atribuídos ao projecto:
No caso em que o projeto está atribuído a um único empregado, o custo do projecto é igual ao custo deste empregado.
No caso em que o projecto está atribuído a uma equipa, o custo do projecto é igual ao custo dos vários empregados envolvidos na equipa.
O projecto deverá suportar a funcionalidade realizar trabalho que deverá corresponder a invocar a funcionalidade de trabalhar dos vários empregados envolvidos:
No caso em que o projeto está atribuído a um único empregado, apenas se considera o trabalho realizado por este empregado.
No caso em que o projecto está atribuído a uma equipa, então tem que se considerar o trabalho de todos os empregados envolvidos na equipa.
Qual é que deve ser o padrão de desenho a aplicar neste caso por forma a que o código da entidade projecto não necessita de distinguir se está atribuído a um empregado individual ou a uma equipa?
Aplique o padrão escolhido neste caso.
Considere a seguinte hierarquia de classes que tem como super tipo a interface Pessoa: Empregado e Estudante concretizam a interface Pessoa; Professor herda de Empregado; e AlunoMestrado herda de Estudante. A interface Pessoa é uma abstracção que define as funcionalidade comuns que devem ser suportadas por cada uma das classes referidas anteriormente. Uma dessas funcionalidades é representada pelo método void trabalha() que representa a funcionalidade de trabalhar. Cada classe tem uma definição do método trabalha() de acordo com a semântica da classe. Pretende-se agora poder ter a possibilidade de acrescentar novo comportamento extra a cada uma das funcionalidades. Por exemplo, ter um conhecimento do trabalho realizado por uma dada pessoa, ou seja, saber quando uma pessoa começou e terminou de trabalhar. Podemos ainda querer compor vários comportamentos extra.
Qual o padrão de desenho a aplicar para concretizar este requisito por forma a não alterar as entidades já existentes? Exemplifique a aplicação do padrão escolhido com a concretização do comportamento extra do registo do início/fim de trabalho, o qual corresponderá a escrever as mensagens "Comecei a trabalhar" e "Acabei de trabalhar" antes e depois de o método trabalha de uma pessoa com registo de fim e início de trabalho ser invocado. Por razões de simplificação considere que apenas existe o método abstracto trabalha em Pessoa.
Suponha que tem a seguinte classe Document (que representa um documento de texto):
private DocumentFormat _format;
public void setWritingFormat(DocumentFormat format) {
* Writes this document into the specified format.
if (_format.getType().equals("WORD")) {
// write document into word format
} else if (_format.getType().equals("RTF")) {
// write document into RTF format
} else if ... // code for other formats
Esta classe tem um custo de manutenção alto devido ao facto de ter que se preocupar com os diferentes formatos de saída suportados. Além disso, caso se queira suportar novos formatos de saída, isto implicará alterações na própria classe, não se seguindo assim o princípio do aberto/fechado.
Qual o padrão ou padrões a aplicar neste caso para resolver os dois problemas indicados?
Exemplifique a aplicação do padrão ou padrões escolhidos realizando as alterações necessárias à classe Document e também as novas entidades a criar (caso sejam necessárias).