Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Escolha uma das opções e acesse esse e outros materiais sem bloqueio. 🤩

Cadastre-se ou realize login

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Prévia do material em texto

Padrões de projeto de software
Aula 7: Padrões GoF – Parte 6
Apresentação
Nesta aula, determinaremos por qual motivo o padrão Iterator permite um trabalho eficiente com complexas estruturas de objetos.
Ilustraremos também de que forma Command e Mediator evitam o alto acoplamento entre objetos que interagem, registrando ainda a
capacidade de Memento para armazenar e recuperar o estado interno deles.
Objetivos
Descrever as características do Command;
Discutir os atributos do Iterator;
Exemplificar os aspectos do Mediator;
Expressar as qualidades do Memento.
 Primeiras palavras
Apresentaremos, nesta aula, quatro padrões comportamentais: Command, Iterator, Mediator e Memento. Um ponto em comum entre
eles é o fato de todos diminuírem o acoplamento entre os objetos, aumentando as chances de reuso do código de um sistema em outros
projetos de sistemas. Veremos agora como:
Evitar o acoplamento de um objeto
solicitante a uma solicitação.
Acessar e percorrer os elementos de
um objeto agregado sem expor sua
representação.
Impedir o acoplamento entre vários
objetos que interagem.
O estado interno de um objeto, sem
a violação de encapsulamento, pode
ser capturado e externalizado para
que possamos posteriormente
restaurá-lo.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
 Command
1. Objetivos
Criado pela Gangue dos Quatro – em inglês, Gang of Four (GoF) –, o Command possui um conceito clássico: “O padrão encapsula um
pedido em um objeto, permitindo, assim, parametrizar clientes com pedidos diferentes, enfileirar pedidos, fazer log de pedidos e dar
suporte a operações de undo”. (GAMMA et al., 1994)
Command se destaca pela grande simplicidade e pela ampla variedade de aplicações que podem ser utilizadas. Parece absurdo o fato de
que possamos ter um padrão que seja apenas uma interface com um método, mas ele vai se revelar muito poderoso e de grande utilidade
para os desenvolvedores de sistemas. Sua simplicidade está demonstrada no padrão Command a seguir:
 
<< interface >>
Command
+Execute()
public interface Command
{
void Execute();
}
A maioria das classes associa um conjunto de métodos a outro correspondente de atributos. Command se diferencia delas por não fazer
isso: ele encapsula uma única função sem nenhum atributo. É como se este padrão transformasse uma função em uma classe.
2. Problema
Command é usado quando o sistema precisa emitir solicitações para objetos sem saber nada sobre a operação solicitada ou o destinatário
dela. Ele separa o objeto que a invoca daquele que sabe como executá-la.
Para conseguir essa separação, o designer cria uma classe base abstrata que mapeia um receptor (um objeto) com uma ação (um ponteiro
para uma função-membro). A classe base contém um método execute() que simplesmente chama a ação no receptor.
Todos os clientes de objetos Command tratam cada objeto como uma caixa preta, simplesmente invocando o método virtual execute() do
objeto sempre que o cliente exigir o serviço dele. O método execute do comando faz com que as peças se juntem.
Uma classe Command contém o seguinte conjunto de elementos:
1 Um objeto.
2 Um método a ser aplicado a ele.
3 Os argumentos a serem passados quando ele for aplicado.
3. Estrutura
Identificaremos a seguir os passos necessários para implementar o Command:
1
Defina uma interface de comando com uma assinatura de método
como execute().
2
Crie uma ou mais classes derivadas que encapsulem algum
subconjunto do seguinte: um objeto receptor, o método a invocar e
os argumentos a serem transmitidos.
3
Instancie um objeto da classe Command para cada solicitação de
execução adiada.
4
Passe o objeto Command do criador (ConcreteCommand) para o
receptor (Receiver).
4
O invocador (Invoker) decide quando irá executar.
4. Diagrama UML do padrão
Conheçamos seus componentes:
Command: Declara uma interface para a execução de uma
operação;
Concrete Command: Estende a interface Command,
implementando o método execute() por meio da invocação
das operações da classe Receiver. Define ainda uma
vinculação entre um objeto Receiver e uma ação (action());
Client: Cria um objeto Concrete Command e estabelece o
seu receptor (Receiver);
 Fonte: (GAMMA et al., 1994)
Invoker: Solicita ao Command a execução da solicitação;
Receiver: Sabe como executar as operações associadas a uma solicitação.
O Client solicita a execução de um comando. O Invoker pega, encapsula e coloca-o em uma fila caso haja algo a fazer primeiramente.
Encarregado de executar (execute) o comando solicitado, ConcreteCommand envia o resultado disso para o receptor (Receiver).
Dica
Command pode usar o padrão Memento para manter o estado necessário para uma operação de desfazer (undo). Este comando – que deve ser
copiado antes de colocado em uma lista de histórico – atua como um Protótipo (Prototype). O padrão Chain of Responsibility pode usá-lo
para representar requisições aos objetos.
Mostraremos agora o uso do Command para controlar os dispositivos de hardware de uma máquina copiadora.
 O uso do Command
 Clique no botão acima.
O uso do Command para controlar os dispositivos de hardware de uma
máquina copiadora
A hierarquia de classes será apresentada a seguir:
A função dessas classes é evidente: fazer uma chamada para o método execute() em LigarScanner ativa o scanner da máquina,
enquanto chamar execute() na classe DesligarCopiadora desliga um motor. O endereço desse motor é passado ao objeto como um
parâmetro para seu construtor. Com essa estrutura em vigor, agora podemos passar objetos Command em torno do sistema e
ativar execute() sem saber exatamente que tipo de comando eles representavam.
Isso simplifica a lógica de construção do sistema, que foi acionado por eventos. Muitos deles foram detectados por sensores.
Durante a impressão de um arquivo, um sensor óptico pode identificar que acabou o papel na bandeja da máquina para a
impressora. Conseguimos implementar isso simplesmente ligando o DesligarImpressora apropriado ao objeto que controlava o
sensor óptico específico.
Essa estrutura simples possui uma enorme vantagem: o sensor não tem ideia do que está fazendo. Sempre que ele detectar um
evento, ele simplesmente chamará execute() no comando ao qual está vinculado. Isso significa que os sensores não precisam
saber sobre a maneira de ligar ou desligar os aparelhos que compõem a copiadora. Sua função se torna incrivelmente simples.
A complexidade relativa à determinação de quais aparelhos ligar ou desligar quando determinados sensores declararem eventos
foi movida para um programa de iniciação. Em algum momento durante a inicialização do sistema, cada sensor será ligado a um
comando apropriado. Isso coloca todas as interconexões lógicas entre os sensores e comanda a fiação em um local, retirando-a do
corpo principal do sistema. Dessa forma, as funcionalidades do sistema podem ser determinadas completamente fora do
programa de iniciação e ajustadas sem recompilação.
O grande benefício de Command foi encapsular a noção de um comando. Este padrão nos permitiu desacoplar as interconexões
lógicas do sistema dos dispositivos que estavam sendo conectados.
Padrões relacionados:
Prototype;
Iterator;
Mediator;
Memento.
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
 Iterator
1. Objetivos
Divulgaremos agora o conceito clássico deste padrão criado pela GoF:
"Um objeto agregado, como uma lista, deve fornecer uma maneira de acessar seus
elementos sem expor sua estrutura interna. Além disso, você pode querer percorrer a
lista de maneiras diferentes, dependendo do que você precisa realizar. Mas você
provavelmente não quer inflar a interface List com operações para buscas diferentes,
mesmo que você possa antecipar as que você precisa. Você também pode precisar ter
mais de uma passagem pendente na mesma lista."
- GAMMA et al., 1994
O padrão Iterator permite fazer tudo isso. A ideia-chave é assumir a responsabilidade pelo acesso e pela passagem do objeto agregado,
colocando-o em um objeto Iterator que definaum protocolo de passagem padrão. A abstração dele é fundamental para uma tecnologia
emergente chamada de programação genérica. Essa estratégia procura separar explicitamente as noções de algoritmo e estrutura de dados.
Sua motivação é:
Promover o desenvolvimento baseado em componentes;
Aumentar a produtividade;
Reduzir o gerenciamento de configurações.
Exemplo
Se você quiser suportar quatro estruturas de dados (matriz, árvore binária, lista vinculada e tabela de hash) e três algoritmos (classificar,
localizar e mesclar), uma abordagem tradicional exigiria por quatro vezes três permutações para desenvolver e manter. Uma abordagem de
programação genérica, por sua vez, iria requerer apenas quatro mais três itens de configuração.
2.Intenção
Dissociar classes e algoritmos de coleção utilizando a abstração das bibliotecas padrões C++ e Java;
Promover para status de objeto completo o percurso de uma coleção;
Permitir travessia polimórfica.
3. Problema
O problema tratado pelo Iterator refere-se à necessidade de abstrairmos o percurso de estruturas de dados totalmente diferentes para que
possam ser definidos algoritmos capazes de interagir com cada uma delas de forma transparente.
4. Estrutura
O processo para implementar o Iterator divide-se em quatro etapas:
1
Adicione um método create_iterator() à classe Aggregate e
conceda o acesso privilegiado à classe Iterator.
2
Crie uma classe ConcreteIterator que possa encapsular o percurso
da classe coleção.
3
Os clientes pedem ao objeto de coleção para criar um objeto
iterador.
4
Eles usam o protocolo next() para acessar os elementos da classe
de coleção.
5. Diagrama UML do padrão
Exporemos agora os seus componentes:
Iterator: Define uma interface para acessar e percorrer
elementos;
ConcreteIterator: Implementa a interface de Iterator e
mantém o controle da posição corrente de navegação na
lista de objetos;
Aggregate: Define uma interface para a criação de um
objeto Iterator;
Concrete Aggregate: Implementa a interface de criação do
Iterator para retornar uma instância adequada da classe
ConcreteIterator.
 Fonte: (GAMMA et al., 1994)
Dica
Java implementa o padrão Iterator em suas coleções. Ele é obtido por meio do método iterator() de Collection, que devolve uma instância de
java.util.Iterator.
Iterator() é um exemplo de Factory Method. Memento, por sua vez, será frequentemente usado em conjunto com o padrão Iterator, que
também pode utilizá-lo para capturar o estado de uma iteração. Afinal, a classe Iterator armazena a classe Memento internamente.
 
Interface java.util.Iterator:
Package java.util;
public interface Iterator<E> {
boolean hasNext();
Object next();
Void remove();
}
Este exemplo mostra o uso uma coleção de livros, usando um iterator para percorrê-la.
 O uso do Iterator
 Clique no botão acima.
O uso do Iterator
Seus principais atores são:
InterfaceIterator: Esta interface representa a classe abstrata que define o iterador;
IteradorLivro: Trata-se da classe concreta que implementa o iterador;
InterfaceContainer: Interface que define a classe agregadora (Aggregate);
ColecaoLivros: Implementação da coleção de livros.
Mostraremos agora o código para as abstrações InterfaceIterator e InterfaceContainer:
Vejamos a seguir o código para classes concretas IteradorLivro e ColecaoLivros. Observe que IteradorLivro é uma classe
aninhada. Dessa forma, ela pode acessar todos os membros de ColecaoLivros, sendo encapsulada para que outras classes não
possam acessá-la. Elas não sabem, portanto, que IteradorLivro usa a classe InterfaceIterator:
 
Interface InterfaceIterator
{
public boolean hasNext();
public Object next();
}
interface InterfaceContainer
{
public InterfaceIterator createIterator();
}
Coleções Java como ArrayList e HashMap têm a sua implementação do padrão Iterator.
Padrões relacionados:
Prototype;
Command;
Mediator;
Memento.
 
class ColecaoLivros implements InterfaceContainer
{
private String m_titulos[] = {"Padrões de Design","Java OO","Métodos Ágeis","Java: Use a Cabeça","Padrões
Ágeis de Projeto"};
public Iterator createIterator()
{
IteradorLivro result = new IteradorLivro();
return result;
}
private class IteradorLivro implements IIterator
{
private int m_position;
public boolean hasNext()
{
if (m_position < m_titulos.length)
return true;
else
return false;
}
public Object next()
{
if (this.hasNext())
return m_titulos[m_position++];
else
return null;
}
}
}
Atenção! Aqui existe uma videoaula, acesso pelo conteúdo online
 Mediator
1. Objetivos
Criado pela GoF, ele pode ser conceituado como o: 
"Processo que define um objeto que encapsula o modo como um conjunto de objetos
interage. O padrão Mediator promove o acoplamento fraco, evitando que objetos
referenciem uns aos outros explicitamente, e permite que suas interações variem
independentemente."
- GAMMA et al., 1994
O uso deste padrão se tornará viável quando for necessário separar a comunicação entre vários objetos com a utilização de uma interface
cuja função é mediar a comunicação entre eles. (LEÃO, 2018)
2. Problema
Como permitir que um grupo de objetos se comunique sem que haja acoplamento entre eles?
Como remover o forte acoplamento presente em relacionamentos muitos-para-muitos?
Como deixar que novos participantes se conectem ao grupo de objetos facilmente?
Normalmente, projetos de desenvolvimento de software orientado a objetos possuem muitas classes em interação. Se não forem utilizados
padrões e princípios para organizar a comunicação entre esses objetos, a estrutura final será uma confusão total, pois cada objeto
dependerá de muitos outros a fim de poder executar sua função. Para evitar estruturas fortemente acopladas, precisamos de um padrão que
facilite a interação entre os objetos de maneira que eles não estejam cientes da existência de outros.
Exemplo
Quando criamos uma tela do sistema, adicionamos todos os tipos de controles necessários (botões, labels, caixa de texto etc.). Eles precisam
interagir uns com os outros. Caso um botão seja pressionado, ele deve saber se os dados são válidos em outros controles.
Obviamente, ao desenvolver uma interface de tela do sistema (formulário), não precisamos alterar cada classe de controle sempre que lhe
adicionarmos um novo controle, porque as operações entre controles são gerenciadas pela própria classe do formulário. Essa classe é
chamada de mediador (Mediator).
3. Estrutura
Exporemos agora a ordenação devida para implementar o Mediator:
1
Identifique uma coleção de objetos intrarrelacionados que se
beneficiariam do desacoplamento mútuo.
2
Encapsule essas interações na abstração de uma nova classe.
3
Crie uma instância desta classe e refaça todos os objetos
intrarrelacionados para eles interagirem apenas com o mediador.
4
Equilibre o princípio de segregação de interface com o
princípio da responsabilidade única.
5
Tenha cuidado para não criar um objeto controlador ou deus.
No padrão Mediator, um objeto mediador deve encapsular a comunicação entre um grupo de objetos. Note que cada objeto
participante deve conhecer o mediador, mas ignorar a existência dos outros objetos: apenas o objeto mediador conhece cada
um dos outros participantes. Ele, portanto, é o responsável pela comunicação entre os demais objetos, recebendo e
repassando requisições entre eles. Toda essa política de comunicação é determinada pelo mediador.
4. Diagrama UML do padrão
A seguir, veicularemos os componentes deste padrão:
Mediator: Define uma interface para comunicação com
objetos de classe Colleague;
ConcreteMediator: Implementa comportamento
cooperativo por meio da coordenação de objetos da classe
Colleague. Ele conhece e mantém seus colegas;
 Fonte: (GAMMA et al., 1994)
Colleague classes: Cada classe Colleague conhece seu objeto Mediator de outra forma. Dessa forma, cada colega se comunicará
com o seu mediador sempre que, de outra forma, tiver de se comunicar com outro colega.
Dica
Mediator e Observer são padrões concorrentes.A diferença entre eles é que este distribui a comunicação utilizando dois tipos de objetos
(observador e assunto), enquanto aquele encapsula a comunicação entre outros.
Mediator é semelhante ao padrão Facade, pois abstrai a funcionalidade das classes existentes. Ele trata da maneira de dissociar remetentes e
destinatários, utilizando remetentes e receptores que fizerem indiretamente referências entre si.
Análise comparativa entre Mediator e Facade:
Mediator (mediador) Facade (fachada)
Um Mediator é utilizado para abstrair as funcionalidades
necessárias de um grupo de objetos para simplificar a interação
deles.
Um Facade é utilizado para abstrair as funcionalidades requeridas
de um subsistema de componentes a fim de prover uma interface
simplificada de alto nível.
Todos os objetos interagem uns com os outros por meio do
mediador. O grupo de objetos sabe da existência dele.
Clientes usam Facade para interagir com um subsistema de
componentes. A existência da fachada é desconhecida pelos
componentes do subsistema.
Como todos os objetos registrados podem se comunicar entre si e
com o mediador, essa comunicação é bidirecional.
Clientes podem utilizar a fachada a fim de enviar mensagens para
os componentes do subsistema, mas o contrário não é permitido,
tornando essa comunicação unidirecional.
Um mediador está no meio de um grupo de objetos que
interagem.
Uma fachada está entre um objeto cliente e um subsistema.
Vejamos a implementação do padrão para um aplicativo de troca de mensagens entre diversas plataformas móveis, como Android e IOS.
 O uso do Mediator
 Clique no botão acima.
O uso do Mediator
O aplicativo é composto de duas classes principais: Mediator e Colleague. Aquele recebe mensagens deste, define qual protocolo
utilizar e, em seguida, envia a mensagem. Já este escolhe como receberá uma mensagem e a enviará para aquele.
Observe que todos os objetos Colleague compartilham um Mediator. A interface define a forma como eles enviam mensagens. A
implementação do método de recepção de mensagens ficará a cargo das subclasses.
A seguir, exprimiremos a implementação da classe Colleague para a comunicação entre as plataformas Android e iOS:
As classes Colleague concretas também são bem simples, definindo apenas como a mensagem será recebida. Divulgaremos agora
a interface comum de qualquer Mediator:
 
public abstract class Colleague {
protected Mediator;
public Colleague(Mediator m) {
mediator = m;
}
public void enviarMensagem(String textodamensagem) {
mediator.enviar(textodamensagem, this);
}
public abstract void receberMensagem(String textodamensagem);
 
public class IOSColleague extends Colleague {
public IOSColleague(Mediator m) {
super(m);
}
@Override
public void receberMensagem(String textodamensagem) {
System.out.println("IOS recebeu: " + textodamensagem);
}
}
 
public class AndroidColleague extends Colleague {
public AndroidColleague Mediator m) {
super(m);
}
@Override
public void receberMensagem(String textodamensagem) {
System.out.println("Android recebeu: " + textodamensagem);
}
}
O Mediator terá de definir uma maneira de enviar mensagens. Vejamos uma implementação concreta dele:
O cliente poderia ser algo do tipo:
Padrões relacionados:
 
public interface Mediator {
void enviar(String textodamensagem, Colleague);
}
 
public class MensagemMediator implements Mediator {
protected ArrayList contatos;
public MensagemMediator() {
contatos = new ArrayList();
}
public void adicionarColleague(Colleague colleague) {
contatos.add(colleague);
}
@Override
public void enviar(String textodamensagem, Colleague) {
for (Colleague contato : contatos) {
if (contato != colleague) {
definirProtocolo(contato);
contato.receberMensagem(textodamensagem);
}
}
}
private void definirProtocolo(Colleague contato) {
if (contato instanceof IOSColleague) {
System.out.println("Protocolo iOS");
} else if (contato instanceof AndroidColleague3 {
System.out.println("Protocolo Android");
} else if (contato instanceof SymbianColleague) {
System.out.println("Protocolo Symbian");
}
}
}
 
public static void main(String[] args) {
MensagemMediator mediador = new MensagemMediator();
AndroidColleague android = new AndroidColleague(mediador);
IOSColleague ios = new IOSColleague(mediador);
mediador.adicionarColleague(android);
mediador.adicionarColleague(ios);
android.enviarMensagem("Oi, Symbian! Eu sou um Android!");
ios.enviarMensagem("Olá a todos, sou um iOs!");
}
Prototype;
Command;
Iterator;
Memento.
 Memento
1. Objetivos
Memento permite que os valores dos atributos sejam salvos em um objeto e depois recuperados. Para isso, usa-se uma classe de
armazenamento de estados, que é comum no uso deste padrão: “Sem violar o princípio de encapsulamento, captura e externaliza o estado
interno de um objeto de forma a poder restaurar o estado desse objeto posteriormente”. (GAMMA et al., 1994)
2. Problema
Como restaurar um objeto de volta ao seu estado anterior?
Exemplo
Operações de desfazer ou reversão.
Às vezes, é necessário salvar o estado interno de um objeto em um instante e ter a capacidade de restaurá-lo para esse estado
posteriormente. Isso é útil em caso de erro ou falha do sistema.
Exemplo
Considere o caso de um objeto de calculadora com uma operação de desfazer. Ela poderia simplesmente manter uma lista de todas as
operações anteriores que realizou, sendo capaz, portanto, de restaurar um cálculo anterior. Isso faria com que o objeto dela se tornasse maior,
mais complexo e mais pesado, já que ele teria de fornecer uma funcionalidade adicional de desfazer e manter uma lista de todas as operações
anteriores. Essa funcionalidade pode ser movida para fora da classe dela a fim de que uma classe externa (vamos chamá-la de desfazer
gerenciador) possa coletar o estado interno da calculadora e salvá-la. No entanto, fornecer ao gerenciador de restauração acesso explícito a
todas as variáveis de estado dela seria impraticável e violaria o princípio de encapsulamento.
3. Estrutura
O padrão de design de Memento define três papéis distintos:
1
Originador (originator)
O objeto que sabe como se salvar.
2
Zelador (caretaker)
O objeto que sabe por que e quando o Originador precisa salvar e
restaurar a si mesmo.
3
Lembrança (memento)
O cofre contém variáveis que são lidas e escritas pelo Originador e
vigiadas pelo Zelador.
Eis o procedimento para implementar este padrão:
1. Identifique os papéis de zelador e originador;
2. Crie uma classe Memento e declare o originador como um amigo;
3. O zelador sabe quando inspecionar o originador;
4. O criador cria um Memento e copia seu estado para ele;
5. O zelador agarra-se a (mas não pode espiar) Memento;
6. O zelador sabe quando reverter o estado salvo do originador;
7. O originador se reinstala usando o estado salvo no Memento.
4. Diagrama UML do padrão
Divulgaremos a seguir os componentes de Memento:
Memento: Este objeto vai manter o estado de origem. É
apenas uma caixa de bloqueio escrita e lida pelo Originator
e acompanhada pelo Caretaker;
Originator: Trata-se do objeto no qual o estado deve ser
salvo. Cria o objeto Memento e o usa no futuro para
desfazer;
Caretaker: Mantém o controle de vários Mementos.
 Fonte: (GAMMA et al., 1994)
Um objeto Caretaker (zelador) realiza uma operação em Originator (originador), tendo a possibilidade de reversão. Ele chama o método
createMemento() no Originator, pedindo que o originador passe a ele um objeto Memento.
Nesse momento, Originator cria um Memento salvando seu estado interno e passando-o para Caretaker, que o mantém e realiza essa
operação. Caso haja a necessidade de desfazê-la, Caretaker chamará o método setMemento() no próprio Originator, passando o objeto
Memento mantido.
Dica
Command pode usar o padrão Memento para manter o estado necessário para uma operação de desfazer (undo). Memento é frequentemente
aplicado em conjunto com o Iterator, que pode utilizar um Memento para capturar o estado de uma iteração.
OIterator armazena o Memento internamente. Usar este padrão pode ser caro a depender da quantidade de informação de estado que deve ser
armazenada dentro do objeto Memento.
Retomemos o exemplo da calculadora sob outro prisma.
 O uso do Memento
 Clique no botão acima.
O uso do Memento
Ela agora apresenta o resultado da adição de dois números, contendo a opção adicional para desfazer a última operação e
restaurar o resultado anterior.
O código-fonte a seguir mostra a interface do objeto Memento para o zelador. Observe que ela é apenas um espaço reservado e
sem métodos para honrar o encapsulamento, pois a lembrança é opaca para o zelador, que nunca opera ou examina os conteúdos
de um Memento:
A interface criada pela classe Originator será designada agora. Ela deve providenciar os métodos necessários para o objeto
originador restaurar seu estado original:
As implementações das classes Originator e Caretaker aparecerão a seguir:
 
package memento;
/**
* Memento interface to CalculatorOperator (caretaker)
*/
public interface PreviousCalculationToCareTaker {
// nenhuma operação permitida para o zelador (caretaker)
}
 
package memento;
/**
* Memento interface to Originator
*
* Esta interface permite ao originador restaurar seu estado
*/
public interface PreviousCalculationToOriginator {
public int getFirstNumber();
public int getSecondNumber();
}
Este código, por sua vez, apresenta a interface da calculadora, que funciona como a interface do originador:
Padrões relacionados:
Prototype;
Command;
Iterator;
Mediator.
 
package memento;
/**
* Memento Object Implementation
*
* Este objeto implementa as interfaces de Originator e CareTaker
*/
public class PreviousCalculationImp implements PreviousCalculationToCareTaker,
PreviousCalculationToOriginator {
private int firstNumber;
private int secondNumber;
public PreviousCalculationImp(int firstNumber, int secondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
}
@Override
public int getFirstNumber() {
return firstNumber;
}
@Override
public int getSecondNumber() {
return secondNumber;
}
}
 
package memento;
/**
* Originator Interface
*/
public interface Calculator {
// criação do Memento
public PreviousCalculationToCareTaker backupLastCalculation();
// definição do estado do Memento
public void restorePreviousCalculation(PreviousCalculationToCareTaker memento);
// serviços atualmente providos pelo originador
public int getCalculationResult();
public void setFirstNumber(int firstNumber);
public void setSecondNumber(int secondNumber);
}
 Atividade
1. Qual padrão tem o objetivo de encapsular um pedido em um objeto, permitindo, assim, parametrizar clientes com pedidos diferentes,
enfileirar pedidos, fazer log de pedidos e dar suporte a operações de undo?
a) Command
b) Iterator
c) Mediator
d) Memento
e) Facade
2. Qual padrão resolve o problema relacionado à necessidade de abstração do acesso a uma lista de elementos armazenados em estruturas
de dados diversas?
a) Integer
b) Memento
c) Mediator
d) Template Method
e) Iterator
3. Qual padrão diminui o acoplamento entre os objetos, permitindo que haja comunicação entre eles?
a) Integer
b) Memento
c) Mediator
d) Template Method
e) Iterator
4. Qual padrão oferece uma maneira simples de salvar valores (estados) internos dos atributos de um objeto, bastando salvar todas as
informações necessárias em uma classe de armazenamento de estados para recuperá-las mais tarde?
a) Integer
b) Memento
c) Mediator
d) Template Method
e) Iterator
NotasReferências
GAMMA, E.; HELM, R.; JOHNSON, R.; VLISSIDES, J. Design patterns: elements of reusable object-oriented software. New York:
Addison-Wesley Professional, 1994.
FRIEMAN, E. Use a cabeça! Padrões de projeto. 2. ed. Rio de Janeiro: Elsevier, 2007.
LEÃO, L. Padrões de projeto de software. Rio de Janeiro: SESES, 2018.
MARTIN, R. C.; MARTIN, M. Agile principles, patterns, and practices in C#. New Jersey: Prentice-Hall, 2006.
Próxima aula
Apresentação dos padrões Observer, State, Strategy e Visitor.
Explore mais
Exemplos de código C# para os padrões:
Command;
Iterator;
Mediator;
Memento.
Exemplos de padrões em Java Design Patterns Command.
javascript:void(0);
javascript:void(0);
javascript:void(0);
javascript:void(0);
javascript:void(0);