Ir para o conteúdo
ou

Software livre Brasil

 Voltar a Gustavo Dutr...
Tela cheia

Facade Pattern com perl orientado a objetos

17 de Outubro de 2009, 0:00 , por Software Livre Brasil - 1Um comentário | Ninguém está seguindo este artigo ainda.
Visualizado 367 vezes

Olá! Faz um tempo que não mexo com perl. Encontrei perdido um arquivo com esse exemplo que fiz em 2008, segundo a data de última modificação. Então, decidi dar continuidade aos posts de design patterns. Esse padrão é bem interessante, poderia ser traduzido para Fachada.

Eu gosto dessa tradução, porque traduz bem direitinho o que ele representa, é uma fachada para “esconder” chamadas de vários métodos de objetos diferentes atrás de um mesmo método. Pense assim:

Toda vez que eu aperto o botão de uma máquina de café e pedir um mocacchino, acontece a mesma coisa:

  • Moe-se o café
  • Pega-se um copo
  • Esquenta-se a água
  • Passa-se o café
  • Coloca-se o café passado no copo
  • Coloca-se o chocolate
  • Coloca-se o leite
  • Apita pra dizer que está pronto

Se olharmos isso com a visão de um pojetista, vemos que temos várias responsabilidades e que não podemos deixar tudo numa mesma classe, como por exemplo:

  • Responsável por moer o café
  • Responsável por colocar algo no copo
  • Responsável por pegar 1 copo novo
  • Responsabilidade de saber quanto de cada ingrediente por no copo
  • Responsabilidade de apitar e escrever nos leds

Enfim, para que o código seja organizado, precisamos distribuir as responsabilidades de acordo com as necessidades e obrigações de cada classe. Porém, cada vez que o botão for pressionado, seria muito cruel ter que chamar várias classes e executar esses métodos que selecionam o copo, moem o grão, etc.

Para esses casos foi pensando o Facade Pattern, ou seja, a Fachada. Todo aquele algoritmo descrito na primeira lista acima, é encapsulado dentro de uma classe específica para a máquina de café, dentro do método pressionaBotao, por exemplo. Chamando o método, ele se encarrega de interagir com os objetos de seleção do copo, do cálculo da quantidade de ingredientes, etc.

Fiz um exemplo em perl, pensando num cinema. Acredito que fique fácil entender a partir dele. Seguem as classes utilizadas:

#!/usr/bin/perl -w
{
	# Classe representando o amplificador
	package Amplifier;
	# construtor
	sub new {
		my $class = shift;
		$class = ref($class) || $class;
		my $this = {};
		bless($this, $class);
		return $this;
	}
	# liga o amplificador
	sub on {
		my $this = shift;
		print "Turning the Amplifier [ON]\n";
	}
	# desliga o amplificador
	sub off {
		my $this = shift;
		print "Turning the Amplifier [OFF]\n";
	}
	# Muda o volume
	sub setVolume {
		my $this = shift;
		$volume = shift;
		print printf "Turning the Amplifiers volume to %d%%\n", $volume;
	}
	# coloca no mudo
	sub mute {
		my $this = shift;
		$this->setVolume(0);
	}
}
 
{
	# Classe representado o aparelho de DVD
	package Dvd;
	# construtor
	sub new {
		my $class = shift;
		$class = ref($class) || $class;
		my $this = {};
		$this->{state} = 'stop';
		$this->{movie} = undef;
		bless($this, $class);
		return $this;
	}
	# liga o dvd
	sub on {
		my $this = shift;
		print "Turning the DVD Player [ON]\n";
	}
	# desliga o dvd
	sub off {
		my $this = shift;
		print "Turning the DVD Player [OFF]\n";
	}
	# da play no filme
	sub play {
		my $this = shift;
		$movie = shift;
		if ($this->{state} eq 'play') {
			$this->{stop}();
			$this->{play}($movie);
		} else {
			$this->{movie} = $movie;
			$this->{state} = 'play';
			print printf "Playing the movie %s\n", $movie
		}
	}
	# da stop no filme
	sub stop {
		my $this = shift;
		if ($this->{state} eq 'play') {
			$this->{state} = 'stop';
			print printf "Stoping the movie %s\n", $this->{movie};
			$this->{movie} = undef;
		}
	}
	# ejeta a bandeja pra por no dvd
	sub eject {
		my $this = shift;
		if ($this->{state} eq 'play') {
			$this->{stop}();
		}
		print "Ejecting the DVD\n";
	}
}
{
	# classe representando o projetor
	package Projector;
	# construtor
	sub new {
		my $class = shift;
		$class = ref($class) || $class;
		my $this = {};
		bless($this, $class);
		return $this;
	}
	# ajusta o canal de vídeo
	sub videoChannel {
		my $this = shift;
		print "Setting Video Channel\n";
	}
	# liga o projetor
	sub on {
		my $this = shift;
		print "Turning the Project [ON]\n";
	}
	# desliga o projetor
	sub off {
		my $this = shift;
		print "Turning the Project [OFF]\n";
	}
}
{
	# Classe representando as luzes do cinema
	package Lights;
	# construtor
	sub new {
		my $class = shift;
		$class = ref($class) || $class;
		my $this = {};
		$this->{state} = 'off';
		bless($this, $class);
		return $this;
	}
	# liga as lâmpadas
	sub on {
		my $this = shift;
		if ($this->{state} eq 'off') {
			print "Turning the Lights [ON]\n";
			$this->{state} = 'on';
		}
	}
	# desliga as lâmpadas
	sub off {
		my $this = shift;
		if ($this->{state} eq 'on') {
			$this->{state} = 'off';
			print "Turning the Lights [OFF]\n";
		}
	}
}
{
	# classe representando uma máquina de pipoca
	package PopcornMachine;
	# construtor
	sub new {
		my $this = {};
		my $class = shift;
		$class = ref($class) || $class;
		$this->{state} = 'off';
		bless($this, $class);
		return $this;
	}
	# liga a máquina
	sub on {
		my $this = shift;
		if ($this->{state} eq 'off') {
			$this->{state} = 'on';
			print "Turning the Popcorn Machine [ON]\n";
		}
	}
	# estoura as pipocas
	sub pop {
		my $this = shift;
		if ($this->{state} eq 'on') {
			print "Poping the corns ;P\n";
		}
	}
	# desliga a máquina
	sub off {
		my $this = shift;
		if ($this->{state} eq 'on') {
			$this->{state} = 'off';
			print "Turning the Popcorn Machine [OFF]\n";
		}
	}
}

A orientação a objetos no perl é meio sinistra. Existem diversas formas de se programar orientado a objetos no perl, eu escolhi esta pois parece mais simples e fácil. Bom, essas são as classes utilizadas:

  • Amplifier
  • DVD
  • Projector
  • Lights
  • PopcornMachine

Bom, cada vez que um filme inicia ou termina no cinema, várias operações são repetidas sempre. Alguém já viu cinema com as luzes acesas? Bem, sempre se desliga as luzes. Então observe a classe abaixo que representa o Facade.

{
	# classe representando o cinema
	package CineFacade;
	# construtor
	sub new {
		my $this = {};
		my $class = shift;
		$class = ref($class) || $class;
		$this->{amplifier} = shift || undef;
		$this->{dvd} = shift || undef;
		$this->{projector} = shift || undef;
		$this->{lights} = shift || undef;
		$this->{popcornMachine} = shift || undef;
		bless ($this, $class);
		return $this;
	}
	# começa a ver o filme
	sub watchMovie {
		my $this = shift;
		$movie = shift;
		# Popcorn machine
		$this->{popcornMachine}->on();
		$this->{popcornMachine}->pop();
		# Home lights
		$this->{lights}->off();
		# Projector
		$this->{projector}->on();
		$this->{projector}->videoChannel();
		# Amplifier
		$this->{amplifier}->on();
		$this->{amplifier}->setVolume(100);
		# DVD
		$this->{dvd}->on();
		$this->{dvd}->play($movie);
	}
	# termina de ver o filme
	sub endMovie {
		my $this = shift;
 
		$this->{popcornMachine}->off();
		$this->{lights}->on();
		$this->{projector}->off();
		$this->{amplifier}->off();
		$this->{dvd}->stop();
		$this->{dvd}->eject();
		$this->{dvd}->off();
	}
}

Observem o método watchMovie e endMovie. Eles chamam operações comum a todas as seções do cinema.
Aqui vai o exemplo de uso do facade no meio da aplicação:

{
	# Exemplo de uso
	$cine = CineFacade->new(
			Amplifier->new(),
			Dvd->new(),
			Projector->new(),
			Lights->new(),
			PopcornMachine->new()
			);
 
	print "Movie Session started: \n\n";
	$cine->watchMovie('Titanic');
 
	print "Movie Session ended: \n\n";
	$cine->endMovie();
}

O output é mais ou menos assim:

Movie Session started: 
 
Turning the Popcorn Machine [ON]
Poping the corns ;P
Turning the Project [ON]
Setting Video Channel
Turning the Amplifier [ON]
Turning the Amplifiers volume to 100%
Turning the DVD Player [ON]
Playing the movie Titanic
 
Movie Session ended: 
 
Turning the Popcorn Machine [OFF]
Turning the Lights [ON]
Turning the Project [OFF]
Turning the Amplifier [OFF]
Stoping the movie Titanic
Ejecting the DVD

Fonte: http://gustavodutra.com/post/288/facade-pattern-com-perl-orientado-a-objetos/

1Um comentário

  • 494f360c8b599ce3c67e0439720ce430?only path=false&size=50&d=404Carlos(usuário não autenticado)
    7 de Janeiro de 2010, 16:46

    Orientação a Objeto

    Gostei muito deste seu artigo, me ajudou bastante a entender a orientação a objeto utilizando o perl.


Enviar um comentário

Os campos são obrigatórios.

Se você é um usuário registrado, pode se identificar e ser reconhecido automaticamente.