Você ainda se lembra de como os bandidos cooperaram no filme da polícia e gangster? Quando uma gangue é roubo, uma ou duas pessoas sempre levam o vento à porta. Se houver algum movimento, os cúmplices internos serão notificados imediatamente para recuar com urgência. Talvez a pessoa que permita que as notícias não conheçam necessariamente todos os cúmplices; E pode haver um novo irmão mais novo que não conhece aquele que deixa as notícias. Mas isso não é nada, não pode afetar suas comunicações porque elas têm um código que foi acordado.
Haha, a relação entre o Air Venter e o ladrão mencionado acima é um exemplo vivo do padrão de observador na realidade.
O modo Observador também é conhecido como modo de publicação/inscrição. O GOF define o padrão do observador da seguinte forma: define uma dependência individual entre os objetos. Quando o estado de um objeto muda, todos os objetos que dependem dele são notificados e atualizados automaticamente.
Aqui, falarei primeiro sobre um princípio importante do design orientado a objetos - o princípio de responsabilidade única. Portanto, cada objeto do sistema deve se concentrar em abstrações discretas no domínio do problema. Portanto, idealmente, um objeto só faz uma coisa. Isso traz muitos benefícios no desenvolvimento: fornece reutilização e manutenção e também é uma boa base para a refatoração.
Portanto, quase todos os padrões de design são baseados nesse princípio básico de design. Eu acho que a origem do modelo Observer deve estar no processamento da GUI e dos dados comerciais, porque a maioria dos exemplos que explica o modelo de observador agora é esse tópico. No entanto, a aplicação do modo Observador não se limita a esse aspecto.
Bem, o entendimento da definição sempre requer instâncias para analisar. Atualmente, as contas de serviço do WeChat são bastante populares. Vamos apresentar o modelo Observer com os antecedentes das contas de serviço do WeChat.
Olhe para uma foto:
Cada usuário possui 3 linhas na figura acima, que são omitidas para deixar a imagem clara.
Como mostrado na figura acima, o número do serviço é o nosso tema e o usuário é o observador. Agora esclarecemos as seguintes funções:
1. Conta de serviço é o tema e os negócios estão empurrando mensagens
2. Os observadores precisam apenas assinar o tópico e serão enviados assim que houver novas notícias.
3. Cancelar a inscrição quando você não deseja esta mensagem de tópico
4. Enquanto a conta de serviço ainda estiver lá, alguém será inscrito. Agora, vamos dar uma olhada no diagrama de aula do padrão de observador:
Em seguida, é o horário do código, simulamos uma conta do WeChat 3D Lottery Service e alguns assinantes.
Primeiro, comece a escrever sobre nossa interface de tópico e interface do observador:
pacote com.zhy.pattern.observer; / ** * Interface de tópicos, todos os tópicos devem implementar essa interface * * @author zhy * */ public / ** * Remova um observador * * @param observer */ public void RemowObServer (Observer Observer); / *** notifique todos os observadores*/ public void notifyObservers (); } pacote com.zhy.pattern.observer; / *** @Author Zhy Todos os observadores precisam implementar essa interface*/ Public Interface Observer {public void update (string msg); }Próxima classe de implementação do número de serviço 3D:
pacote com.zhy.pattern.observer; importar java.util.arraylist; importar java.util.list; classe pública ObjectFor3D implementa o assunto {private List <Beserver> Observers = new ArrayList <Beserver> (); / *** Número da loteria 3D*/ String privada msg; @Override public void RegisterObServer (Observer Observer) {Observers.add (Observer); } @Override public void RemowObServer (Observer Observer) {int index = observers.IndexOf (Observer); if (index> = 0) {observers.remove (index); }} @Override public void notifyObServers () {for (observador observador: observadores) {observer.update (msg); }} / ** * Mensagem de atualização do tópico * * @param msg * / public void setmsg (string msg) {this.msg = msg; notifyObServers (); }}Simular dois usuários:
pacote com.zhy.pattern.observer; classe pública Observer1 implementa observador {sujeito privado; public Observer1 (sujeito) {this.subject = sujeito; sujeito.ReGisterObServer (this); } @Override public void update (string msg) {System.out.println ("Observer1 obtém o número 3D ->" + msg + ", eu quero escrever."); }} pacote com.zhy.pattern.observer; classe pública Observer2 implementa observador {sujeito privado; public observador2 (sujeito) {this.subject = sujeito; sujeito.ReGisterObServer (this); } @Override public void update (string msg) {System.out.println ("Observer2 recebe o número 3D ->" + msg + "eu quero contar aos meus colegas de quarto."); }} Pode -se observar que todos os usuários que assinam mensagens são mantidos na conta de serviço e todos os usuários são notificados quando há uma nova mensagem na conta de serviço. Toda a arquitetura é um acoplamento frouxo e a implementação do tema não depende do usuário. Quando um novo usuário é adicionado, o código do tema não precisa ser alterado; Como o usuário processa os dados obtidos não têm nada a ver com o tema;
Finalmente, veja o código de teste:
pacote com.zhy.pattern.observer.test; importar com.zhy.pattern.observer.objectfor3d; importar com.zhy.pattern.observer.observer; importar com.zhy.pattern.observer.observer1; importar com.zhy.pattern.observer.observer2; importar com.zhy.pattern.observer.subject; public class Test {public static void main (string [] args) {// simular um número de serviço 3D ObjectFor3d subjectFor3d = new ObjectFor3d (); // cliente1 observador observador1 = new Observer1 (subjectFor3D); Observer Observer2 = new Observer2 (SubjectFor3D); subjectFor3D.Setmsg ("O número 3D de 20140420 é: 127"); SubjectFor3D.Setmsg ("O número 3D de 20140421 é: 333"); }}Resultado da saída:
Observer1 Obtenha o número 3D -> O número 3D de 20140420 é: 127, quero anotar. Observer2 recebe o número 3D -> O número 3D de 20140420 é: 127 Quero contar aos meus colegas de quarto. Observer1 Obtenha o número 3D -> O número 3D de 20140421 é: 333, eu quero escrever. Observer2 recebe o número 3D -> O número 3D de 20140421 é: 333 Quero contar aos meus colegas de quarto.
Existem muitos lugares no JDK ou Andorid que implementam o modo Observer, como xxxview.addxxxlistenter. Obviamente, xxxview.setOnxxxListener não é necessariamente um modo de observador, porque o modo Observador é um relacionamento um para muitos. Para o setxxxlistener, é um relacionamento de 1 a 1 e deve ser chamado de retorno de chamada.
Parabéns por aprender o modo de observador. O modo de observador acima nos permite escrevê -lo do zero. Obviamente, o Java nos ajudou a implementar o modo Observer, com a ajuda de java.util.observable e java.util.observer.
Abaixo, usamos classes internas de Java para implementar o padrão de observador:
Primeiro de tudo, há um tema do número de serviço de loteria 3D:
pacote com.zhy.pattern.observer.java; importar java.util.observable; classe pública SubjectFor3D estende observável {private string msg; public String getMsg () {return msg; } / ** * Mensagem de atualização do tópico * * @param msg * / public void setmsg (string msg) {this.msg = msg; setChanged (); notifyObServers (); }}A seguir, o tema de um número de serviço de bola de cor dupla:
pacote com.zhy.pattern.observer.java; importar java.util.observable; classe pública SubjectForsSq estende observável {private string msg; public String getMsg () {return msg; } / ** * Mensagem de atualização do tópico * * @param msg * / public void setmsg (string msg) {this.msg = msg; setChanged (); notifyObServers (); }}Finalmente, nossos usuários:
pacote com.zhy.pattern.observer.java; importar java.util.observable; importar java.util.observer; classe pública Observer1 implementa observador {public void registrsubject (observável observável) {observable.addobserver (this); } @Override public void update (obsertable o, objeto arg) {if (o instanceof subjectFor3d) {subjectFor3d subjectFor3d = (sujeitoFor3d) o; System.out.println ("SubjectFor3D da msg ->" + subjectFor3d.getmsg ()); } if (o instanceof subjectForsSq) {subjectForSSq substetForsSq = (sujeitoForSSQ) o; System.out.println ("SubjectForSSQ da msg ->" + sujeito SubstetForsq.getMsg ()); }}}Veja um código de teste:
pacote com.zhy.pattern.observer.java; Public class Test {public static void main (string [] args) {sujeitoFor3D SubjectFor3D = new SubjectFor3D (); SubstetForSSQ sujeitoForSSQ = new SubjectForsSq (); Observer1 Observer1 = new Observer1 (); observer1.ReGisterSubject (SubjectFor3D); observer1.ReGisterSubject (SubjectForsSQ); SubjectFor3D.Setmsg ("Hello 3D'Nums: 110"); SubjectForsSq.Setmsg ("SSQ'NUMS: 12,13,31,5,4,3 15"); }}Resultados do teste:
MSG STEIITFOR3D -> Olá 3d'nums: 110 MSG da SubstetForSq -> SSQ'NUMS: 12,13,31,5,4,3 15
Pode-se observar que, usando classes internas de Java para implementar o padrão do observador, o código é muito conciso. A propósito, AddObServer, RemoneBServer, notifyObservers foram implementados para nós. Tudo o que podemos ver que observável é uma classe, não uma interface. Basicamente, o livro tem uma atitude negativa em relação ao design de Java. Parece que o padrão de observador interno de Java viola o princípio da programação orientada para interface. No entanto, se você pensar bem, está realmente escrevendo o padrão de observador aqui (nossa própria implementação). A ideia da interface é muito boa, mas se você continuar adicionando muitos tópicos agora, o DDOBSERVER, REPOTOBSERVER, notifyObservers para cada tópico é basicamente o mesmo. As interfaces não podem implementar a reutilização do código e não há como usar o modo combinado para alcançar a reutilização desses três métodos, então acho razoável implementar esses três métodos na classe aqui.