Mediator Pattern em ColdFusion

On 13 de outubro de 2014, in CFML, Design Pattern, by andersonstraube

Um mediator, em linguagem de programação de computadores, é quem desacopla e gerencia as colaborações entre um grupo de objetos. Define um objeto que encapsula as interações dentre desse grupo.
É um dos 23 padrões de projetos descritos para reutilização de softwares orientados a objetos. Ele permite a unificação da interface de um sistema. Esse padrão é considerado um padrão comportamental devido à maneira como ele pode alterar a execução do software.
Normalmente, um programa é feito por um número muito grande de classes. Então, a lógica e o código são distribuídos entre essas classes. No entanto, quanto mais classes houver no seu projeto, a comunicação entre essas classes será mais complexa. Isso faz com que a leitura e a manutenção do programa fique mais difícil, tal situação acarreta na dificuldade de mudanças no projeto, já que, uma simples mudança pode afetar todo o código e as outras classes.
Com o padrão mediator, a comunicação entre os objetos é encapsulada com um objeto mediador. Isso reduz a dependência entre os objetos que estão se comunicando.
Fonte: http://pt.wikipedia.org/wiki/Mediator

O padrão Mediator fornece uma técnica para tratar a lógica de comunicação complicada entre vários objetos que precisam interagir uns com os outros.

Quando usar?

Abaixo está um exemplo desse tipo de comunicação:


mediator

Como vemos na imagem, todos os objetos se comunicam entre si. Em uma manutenção isso se torna um problema pois uma alteração em um dos objetos pode afetar todo o resto pois eles estão fortemente acoplados, ou seja, cada objeto precisa saber sobre todos os outros objetos.
Em tal situação podemos usar o Mediator, nós criamos uma classe controladora e ela tem a referência de todas as outras classes que por sua vez tem apenas uma referência que é o nosso Mediator, ele é o responsável por controlar o fluxo entre todos os objetos. Aplicando este padrão devemos ter algo parecido com isso:

mediator

Vamos a um exemplo prático:

Criaremos um aplicativo bem simples para controle de Voo. Antes de decolar precisamos nos certificar de uma série de fatores, tais como: nível de combustível, rodas, motor, piloto, etc…
Nosso exemplo hipotético deve conter os seguintes componentes/classes:

– Aviacao
– Motor
– Rodas
– Piloto

Diagrama:

diagrama mediator

Cada componente vai ter um método isPronto() onde retornará se o objeto foi inicializado e está pronto para uso, um componente precisa verificar se o outro está pronto, por exemplo, a classe piloto deve assegurar de que o Motor está ligado, as Rodas foram verificadas assim como a classe Aviação deve verificar o nível de combustível antes de permitir o voo e assim por diante. Existe então um forte acoplamento entre as classes e duplicação de código em cada uma delas, isso vai ser mais grave ainda se ao longo de tempo precisamos adicionar novas classes pois precisamos replicar essa lógica.

Implementação do Mediator

Aplicando este padrão, as nossas classes não vão mais se comunicar umas com as outras, todos os componentes se comunicam apenas com o Mediator, ele é o único que manterá uma referência de todas as classes envolvidas. Com isso temos algumas vantagens:

– Componentes fracamente acoplados;
– Maior flexibilidade de código;
– Controle centralizado: o Mediator encapsula a complexidade da comunicação ou a forma como os objetos interagem entre si, isso deixa a lógica mais clara e centralizada.

Aplicando o padrão Mediator devemos ter algo parecido com isso:

diagrama mediator

Vamos ao código:

Aviacao.cfc


<cfcomponent displayname="Aviacao" output="false">
	<cfscript>
		variables._nivelCombustivel = 5000;
	</cfscript>
	<cffunction name="init" access="public" returntype="Aviacao">
		<cfreturn this />
	</cffunction>
	<cffunction name="isPronto" access="public" returntype="boolean">
		<!--- Só libera a partida se houver mais do que 3000 de combustível --->
		<cfif variables._nivelCombustivel gte 3000 >
			<cfoutput>Aviacao OK!<br></cfoutput>
			<cfreturn true />
		<cfelse>
			<cfoutput>Aviacao Fail!<br></cfoutput>
			<cfreturn false />
		</cfif>
	</cffunction>
</cfcomponent>

Motor.cfc


<cfcomponent displayname="Motor" output="false">
	<cffunction name="init" access="public" returntype="Motor">
		<cfreturn this />
	</cffunction>
	<cffunction name="darPartida" access="public" returntype="void">
		<!--- whatever --->
	</cffunction>
	<cffunction name="isPronto" access="public" returntype="boolean">
		<cfoutput>Motor OK!<br></cfoutput>
		<cfreturn true />
	</cffunction>
</cfcomponent>

Piloto.cfc


<cfcomponent displayname="Piloto" output="false">
	<cffunction name="init" access="public" returntype="Piloto">
		<cfreturn this />
	</cffunction>
	<cffunction name="isPronto" access="public" returntype="boolean">
		<cfoutput>Piloto OK!<br></cfoutput>
		<cfreturn true />
	</cffunction>
</cfcomponent>

Roda.cfc


<cfcomponent displayname="Roda" output="false">
	<cffunction name="init" access="public" returntype="Roda">
		<cfreturn this />
	</cffunction>
	<cffunction name="isPronto" access="public" returntype="boolean">
		<cfoutput>Rodas OK!<br></cfoutput>
		<cfreturn true />
	</cffunction>
</cfcomponent>

VooMediator.cfc


<cfcomponent displayname="VooMediator" output="false">
	<!--- o Mediator deve ter conhecimento de todos os objetos envolvidos no processo --->
	<cfscript>
		variables._aviacao = "";
		variables._roda    = "";
		variables._motor   = "";
		variables._piloto  = "";
	</cfscript>
	<cffunction name="init" access="public" returntype="VooMediator">
		<cfargument name="aviacao" type="Aviacao" hint="Objeto Aviacao">
		<cfargument name="roda"    type="Roda"    hint="Objeto Roda">
		<cfargument name="motor"   type="Motor"   hint="Objeto Motor">
		<cfargument name="piloto"  type="Piloto"  hint="Objeto Piloto">
		<cfset variables._aviacao = arguments.aviacao />
		<cfset variables._roda    = arguments.roda />
		<cfset variables._motor   = arguments.motor />
		<cfset variables._piloto  = arguments.piloto />
		<cfreturn this />
	</cffunction>
	<!--- Verifica se o avião está pronto para decolar --->
	<cffunction name="isPronto" access="public" returntype="boolean">
		<cfreturn variables._piloto.isPronto() and variables._motor.isPronto() and variables._roda.isPronto() and variables._aviacao.isPronto() />
	</cffunction>
</cfcomponent>

test.cfm


<cfscript>
	aviacao = CreateObject("component","Aviacao").init();
	motor = CreateObject("component","Motor").init();
	roda = CreateObject("component","Roda").init();
	piloto = CreateObject("component","Piloto").init();
	vooMediator = CreateObject("component","VooMediator").init(  aviacao: aviacao, roda: roda, motor: motor, piloto: piloto );
	if ( vooMediator.isPronto() ) {
		writeoutput("Pronto para decolar!");
	}
</cfscript>

A saída será:

Piloto OK!
Motor OK!
Rodas OK!
Aviacao OK!
Pronto para decolar!

A utilização deste padrão pode impactar na performance da aplicação uma vez que toda comunicação passa pelo Mediator, isso pode se tornar um gargalo no sistema, por isso é importante avaliar onde é mais coerente aplicá-lo.

Até a próxima, abraço.

Tagged with:  

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *