O Mediator, como o nome sugere, irá mediar essa colaboração, encapsulando toda a complexabilidade do comportamento conjunto em um objeto mediator.
Um exemplo dessa colaboração é um sistema de auto-completar onde o usuário digita os termos em um campo de texto e um outro elemento vai recebendo as dicas, assim que o input tem seu estado modificado (evento onchange) ele avisa o seu mediator que fará o trabalho e repassará para o seu outro objeto que seria uma lista com as sugestões:
Utilizando Javascript para coordenar a interface de usuário, teríamos o seguinte:
index.html
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br"> <head> <title>Mediator</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="public/css/style.css" type="text/css" /> </head> <body onload="main();"> <form id="fMediator" action="" method="post" onsubmit="return false; void(0);"> <fieldset> <label for="iNome"> <span>Nome: </span> <input type="text" id="iNome" name="iNome" /> </label> <ul id="lTips"></ul> </fieldset> </form> <script type="text/javascript" src="public/js/Ajax.js"></script> <script type="text/javascript" src="public/js/AbstractColleague.js"></script> <script type="text/javascript" src="public/js/InputColleague.js"></script> <script type="text/javascript" src="public/js/ListColleague.js"></script> <script type="text/javascript" src="public/js/Mediator.js"></script> <script type="text/javascript"> function main(){ var server = new Mediator( 'test.php' ); var input = new InputColleague( document.getElementById( 'iNome' ) ); var list = new ListColleague( document.getElementById( 'lTips' ) ); input.setMediator( server ); list.setMediator( server ); server.add( input ); server.add( list ); } function muda( nome ){ document.getElementById( 'iNome' ).value = nome; document.getElementById( 'lTips' ).innerHTML = ''; } </script> </body> </html>
AbstractColleague.js
/** * Interface para implementação de um Colleague * @constructor */ function AbstractColleague(){}; /** * Template method para envio de uma mensagem para o mediator * @param String message A mensagem que será enviada para o mediator */ AbstractColleague.prototype.send = function( message ){ this.mediator.send( message , this ); }; /** * Template method para definição do Mediator * @param Mediator mediator */ AbstractColleague.prototype.setMediator = function( mediator ){ if ( mediator instanceof Mediator ){ this.mediator = mediator; } else { throw 'Opz, precisamos de um Mediator'; } }; /** * Template method para recuperação do Mediator * @return Mediator */ AbstractColleague.prototype.getMediator = function(){ return this.mediator; }; /** * Recebe a notificação do mediator caso um Colleague tenha seu estado modificado. * Precisa ser implementado nos Colleagues * @param String message */ AbstractColleague.prototype.notify = function( message ){};
InputColleague.js
/** * Implementação de do input * @param input Objeto do input onde o usuário irá digitar * @constructor */ function InputColleague( input ){ var obj = this; var $_ = { onfocus : function(){ this.onkeydown = function( evt ){ if ( evt.keyCode >= 60 ){ if ( this.timer ) clearInterval( this.timer ); this.timer = setInterval( function( temp ){ clearInterval( temp.timer ); obj.getMediator().send( input.value , obj ); } , 10 , this ); } } }, onblur : function(){ delete this.onkeydown; } }; input.onfocus = $_.onfocus; input.onblur = $_.onblur; this.input = input; }; InputColleague.prototype = new AbstractColleague(); /** * Recebe a notificação do mediator que seu Colleague teve seu estado modificado * @param String message */ InputColleague.prototype.notify = function( message ){ this.input.value = message; };
ListColleague.js
/** * Implementação da listagem de sugestões * @param input Objeto do UL que receberá as LIs * @constructor */ function ListColleague( list ){ this.list = list; }; ListColleague.prototype = new AbstractColleague(); /** * Recebe a notificação do mediator que seu Colleague teve seu estado modificado * @param String message */ ListColleague.prototype.notify = function( message ){ this.list.innerHTML = message; };
Com todos os Colleagues definidos, vamos definir agora o Mediator para um auto completar:
Mediator.js
/** * Mediator * @param String url A URL que será usada para recuperar as sugestões do banco de dados * @construct */ function Mediator( url ){ this.ajax = new Ajax(); this.colleagues = new Array(); this.url = url; }; /** * Adiciona um Colleague que será mediado pelo Mediator * @param Colleague colleague */ Mediator.prototype.add = function( colleague ){ if ( colleague instanceof AbstractColleague ){ this.colleagues.push( colleague ); } else { throw 'Opz, precisamos de um Colleague'; } }; /** * Usado pelos Colleagues para notificar uns aos outros sobre suas mudanças de estado * @param String message * @param Colleague colleague */ Mediator.prototype.send = function( message , colleague ){ if ( colleague instanceof AbstractColleague ){ var $this = this; message = [ 'message' , escape( message ) ].join( '=' ); this.ajax.open( 'POST' , this.url , true ); this.ajax.send( message ); this.ajax.onreadystatechange = function(){ if ( this.readyState == 4 ){ for ( var obj in $this.colleagues ){ if ( $this.colleagues[ obj ] !== colleague ){ $this.colleagues[ obj ].notify( this.responseText ); } } } } } else { throw 'Opz, precisamos de um Colleague'; } };
Para a parte do servidor usaremos um PHP bem simples que apenas receberá a requisição e retornará um conjunto de <li> que representará as sugestões:
test.php
<?php $headers = getallheaders(); if ( isset( $headers[ 'X-Requested-With' ] ) && ( $headers[ 'X-Requested-With' ] == 'XMLHttpRequest' ) ){ if ( ( $_SERVER[ 'REQUEST_METHOD' ] == 'POST' ) && isset( $_POST[ 'message' ] ) ){ $message = sprintf( '%s%%' , $_POST[ 'message' ] ); $pdo = new PDO( 'mysql:host=127.0.0.1;dbname=test' , 'usuario' , 'senha' ); $stm = $pdo->prepare( 'SELECT `u`.`usuariosNome` FROM `Usuarios` AS `u` WHERE `u`.`usuariosNome` LIKE :nome;' ); $stm->bindParam( ':nome' , $message ); if ( $stm->execute() ){ $i = 0; foreach ( $stm->fetchAll( PDO::FETCH_OBJ ) as $row ){ printf( '<li><a href="#" onclick="muda(\'%s\');">%s</a></li>' , $row->usuariosNome , $row->usuariosNome ); } } else { header( sprintf( '%s 500 Internal Server Error' , $_SERVER[ 'SERVER_PROTOCOL' ] ) ); var_dump( $stm->errorInfo() ); } } else { header( sprintf( '%s 400 Bad Request' , $_SERVER[ 'SERVER_PROTOCOL' ] ) ); } } else { header( sprintf( '%s 400 Bad Request' , $_SERVER[ 'SERVER_PROTOCOL' ] ) ); }
Para esse exemplo foi utilizado um banco de dados MySQL com uma tabela de usuários com a seguinte estrutura:
CREATE SCHEMA IF NOT EXISTS `test`; CREATE TABLE IF NOT EXISTS `test`.`Usuarios` ( `idUsuarios` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT, `usuariosNome` VARCHAR(45) NOT NULL, PRIMARY KEY(`idUsuarios`), INDEX `usuarios`(`usuariosNome` ASC) ) ENGINE = MyISAM DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci;
E os seguinte dados:
INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Joao'); INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Joao Batista'); INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Joao Batista Neto'); INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Joao Neto'); INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Jose'); INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Juliano'); INSERT INTO `test`.`Usuarios` (`idUsuarios`, `usuariosNome`) VALUES (NULL, 'Julio');
E para deixar a interface de usuário mais amigável a seguinte folha de estilos:
style.css
* { margin : 0; padding : 0; border : none; text-decoration : none; } body, html { margin : 10px; font-family : Arial, Helvetica; font-size : 14px; } form input#iNome { width : 160px; border : 1px solid #dadada; *margin : 0px 0px 0px 4px; } form label span { display : inline-block; width : 50px; text-align : right; } ul#lTips { border : 1px solid #dadada; width : 160px; max-height : 100px; overflow : auto; margin : 0px 0px 0px 54px; *height : 0px; } ul#lTips li a { display : block; width : 100%; line-height : 24px; height : 24px; color : #333333; } ul#lTips li a:hover { color : #FF0000; }
Agora, sempre que o usuário digitar alguma coisa no input text o Mediator será avisado, enviará a requisição ao servidor e recuperará a lista de sugestões, essa lista é repassada ao outro Colleague responsável por montar a lista de sugestões.
;)
Procurando por Design Pattern, encontrei seu site João, espero que continue postando sobre o assunto, pq é complicado encontrar material em português. Parabéns.
ResponderExcluirabrs