State: diferenças entre revisões

37 bytes adicionados ,  15h20min de 7 de fevereiro de 2014
(A categoria Design Patterns não existe na Wikipedia, então a alterei para Padrões de Projetos, podendo assim o usuário ser redirecionado corretamente.)
public class Main {
 
public static void main(String argv[] args) {
 
Livro l1 = new Livro("Design Patterns");
Livro l2 = new Livro("Java Programming Language");
 
l1.solicitar(); // DisponivelDisponível -> PrestadoEmprestado
l1.solicitar(); // Ops, o livro já está prestadoemprestado
l1.devolver(); // PrestadoEmprestado -> DisponibleDisponível
 
l2.devolver(); // nada, o livro já está disponível
<source lang="java5">
/**
* Livro define o contexto para este exemplo simples de padraopadrão estado.
* Um Livro puedepode estar em dosdois estados: Disponível you PrestadoEmprestado, de tal modo que
* se escolhemosescolhermos por representar o estado com um atributo, os métodos da
* claseclasse Livro acabariam por convertirconverter-se em condicionais sobre esse estado .
*/
 
public class Livro {
 
private EstadoLibroEstadoLivro _estadoestado; // implementa associação com o estado
// O construtor da classe, además de inicializar o título do
 
private String _titulotitulo;
 
// O construtor da classe, ademásalém de inicializar o título do
// livro, define o estado inicial (Disponível). Como neste caso
// os estados de livros têm o seu próprio estado, usamos um singletonSingleton.
 
public Livro(String titulo) {
_titulothis.titulo = titulo;
_estadothis.estado = Disponivel.instancia();
}
 
public String toString() { return (_titulo + " (" + _estado + ")" ); }
return (this.titulo + " (" + this.estado + ")" );
}
 
// Este método modifica o estado do livro. Problema: o método deve
// ser acessado a partir de uma classe externa (EstadoLibroEstadoLivro), o que exclui
// a visibilidade private e protectprotected. public é demasiado geral pois
// *todas* as classes podepodem acessar o método... Neste caso, sugere-se a
// visibilidade de package, com Livro e os seus estados no mesmo package...
 
void estabelecerEstado(EstadoLibroEstadoLivro estado) {
System.out.println("Transitando de " + this.estado + " a " + estado);
void estabelecerEstado(EstadoLibro estado) {
Systemthis.out.println("Transitando de " + _estado + " a "estado += estado);
_estado = estado;
}
 
// Os métodos de dependentes do estado delegam o comportamento
// definido para cada estado. Uma vez que vamos a responsabilizardar aos estados
// estadosa responsabilidade de realizar as transições, passamos o livro ao estado
// ao estado para que possa, se lhe interessainteressar, chamar estabelecerEstado.
 
public void devolver() { _estado.devolver(this); }
this.estado.devolver(this);
}
public boolean solicitar() { return _estado.solicitar(this); }
return this.estado.solicitar(this);
 
}
//-------- privadas ---------
 
private EstadoLibro _estado; // implementa associação com o estado
private String _titulo;
}
 
<source lang="java5">
/**
* Esta é a classe abstrata que define as operações específicas do Estado.
* del estado. Os métodos podem ser declarados abstratos, de modo que as classes
* as classes derivadas têmsejam queforçadas implementara implementá-los forzosamente, oou podem ter uma
* ter uma implementação por defeitopadrão, definida neste nível.
*/
 
 
// Os métodos devolver e solicitar são abstratos (devem ser implementados
// pelos estados concretos) e saosão tomados como argumento livro, se
// desejamosdesejarmos aceder posteriormente aos atributos e métodos do mesmo.
 
abstract public abstract void devolver(Livro livro);
abstract public abstract boolean solicitar(Livro livro);
 
// Além disso, adicionamos um método com um stringString que identifica o statusestado
// do livro -- a definição estabelece um valor por defeitopadrão que será
// usado se as sub-clasessubclasses naonão redefinemo redefinirem.
 
public String toString() { return "Desconhecido"; }
 
public String toString() { return "Desconhecido"; }
return "Desconhecido";
}
}
 
/**
* Um dos estados concretos do livro. A classe Disponivel faz a
* transição Disponivel -> PrestadoEmprestado ao chamar ao método solicitar. Ignora
* Ignora as devolucioesdevoluções (naonão se contemplam várias cópias do mesmo livro)
*/
 
public class Disponivel extends EstadoLibroEstadoLivro {
 
// Uma vez que em esteneste exemplo os estados dos livros nao vaonão avão conter
// atributos dependentes do contexto, fazemos com que Disponivel seja um
// Singleton
 
private static Disponivel instancia; // Instancia do Singleton Disponivel
 
protected Disponivel() {}
 
public static Disponivel instancia() {
if (_instanciathis.instancia == null)
_instanciathis.instancia = new Disponivel();
 
return _instanciathis.instancia;
}
 
// Métodos específicos deste estado concreto. Solicitarsolicitar modifica o estado
// do livro, enquanto que devolver simplesmente o ignora.
 
public boolean solicitar(livroLivro livro) {
System.out.println("Atendendo pedido do livro " + livro);
livro.estabelecerEstado(PrestadoEmprestado.instancia());
return true;
}
 
public void devolver(livroLivro livro) {
System.out.println("Oba... já tenho o livro " + livro);
}
// Redefine o nome do estado...
 
public String toString() { return "Disponivel"; }
return "Disponivel";
 
}
//--------- privadas ------------
 
// Instancia do Singleton Disponivel
 
private static Disponible _instancia;
}
 
 
/**
* Um dos estados concretos do livro. A classe PrestadoEmprestado faz a
* transição PrestadoEmprestado -> Disponivel ao chamar ao método devolver. Ignora
* Ignora os pedidos (não se contemplam reservas).
*/
 
public class Prestado extends EstadoLivro {
 
// Dado que neste exemplo os estados dos livros não vão a conter
// atributos dependentes do contexto, fazemos com que Prestado seja unEmprestado
// seja um Singleton.
 
private static Prestado instancia; // Instância do Singleton Emprestado
 
protected PrestadoEmprestado() {}
 
public static PrestadoEmprestado instancia() {
if (_instanciathis.instancia == null)
_instanciathis.instancia = new PrestadoEmprestado();
 
return _instancia;
}
 
// Métodos específicos deste estado concreto. Devolver faz a transicãotransição
// apara DisponibleDisponivel, enquanto que solicitar rejeita.
 
public boolean solicitar(livroLivro livro) {
System.out.println("ElO livro " + livro + " não está disponível");
return false;
}
 
public void devolver(livroLivro livro) {
System.out.println("Ok.OK, Oo livro " + livro + " foi devolvido");
livro.estabelecerEstado(Disponivel.instancia());
}
// Redefine o nome do estado
 
public String toString() { return "Prestado"; }
return "Emprestado";
 
}
//--------- privadas ------------
 
// Instancia do Singleton Prestado
 
private static Prestado _instancia;
}
 
== Conclusões ==
 
O padrão não indica exatamente dondeonde definir as transições de um estado para outro. Há duas maneiras de contornar isso:. Uma delas é definir essas transições dentro da classe Contexto, a outra é definir essas transições nas subclasses de Estado. É mais conveniente utilizar a primeira solução quando o critério a ser aplicado é fixo, ou seja, não mudará. O segundo é conveniente quando este critério é dinâmico,. aA desvantagem aqui é apresentada na dependência de código entre as subclasses.
 
Precisamos também avaliar a implementação ao criar instanciasinstâncias de estado concreto diferentes ou usar a mesma instância compartilhada. Isto irá depender se a mudança de estado é menos frequente ou mais frequente, respectivamente.
[[Categoria:Padrões de projeto de software]]
69

edições