Приглашаем посетить
Чехов (chehov-lit.ru)

Hack 76. Simplify APIs Using a Façade

Previous
Table of Contents
Next

Hack 76. Simplify APIs Using a Façade

Hack 76. Simplify APIs Using a Façade Hack 76. Simplify APIs Using a Façade

Use the Façade pattern to simplify the API that you present to other programmers.

This is one of the patterns I really wish more programmers would use, and not just because of that fancy squiggle under the c in façade. It's because creating a façade means that some other programmer has thought of me and made sure I have just the information I need (and nothing else that I can screw up).

Take a sample logging API, such as the one shown in Figure 7-10.

Figure 7-10. The logging API with a simple façade
Hack 76. Simplify APIs Using a Façade


This API can log to XML, text, or both. Wow. As a peer programmer, I'm impressed with the skill of the coding. There seem to be methods for everything; starting a message, adding text, cleaning up…even handling XML and text easily.

But what I really want to know is which method to use and when to use it. That's precisely what a façade does: it ensures that I use the API correctly. The façade in this example is the list of three functions with the line through it on the lefthand side. That line is a sort of theoretical bar that says, "I'll handle the stuff to the right; just call my methods, and I'll take care of the rest."

Not only does the façade simplify APIs, but it also hides implementation details from the client; in fact, the implementation can change without clients even knowing about it. This is at least as important as the simplification that façades bring. Remember, loose coupling means strong and reliable systems.

7.11.1. The Code

Save the code in Example 7-12 as test.php.

Example 7-12. The log test code
	<?php
	require( "log.php" );
	log_start( "mylog" );
	log_message( "Opening application" );
	log_message( "Logging a message" );
	log_message( "Shutting down" );
	log_end();
	?>

Save the code in Example 7-13 as log.php.

Example 7-13. The log façade
	<?php
	require( "log_impl.php" );

	function log_start( $fileName )
	{
	  Log::instance()->start( $fileName );
	}

	function log_message( $message )
	{
	  Log::instance()->add( $message );
	}

	function log_end()
	{
	  Log::instance()->end();
	}
	?>

Save the code in Example 7-14 as log_impl.php.

Example 7-14. The log library behind the façade
	<?php
	class XMLLog
	{

	  private $fileName;
	  private $doc;
	  private $log;

	  public function XMLLog( $fileName )
	  {
	    $this->fileName = $fileName;

		$this->doc = new DOMDocument();
		$this->doc->formatOutput = true;
		$this->log = $this->doc->createElement( "log" );
		$this->doc->appendChild( $this->log );
	  }

	  public function add( $message )
	  {
	    $mess_obj = $this->doc->createElement( "message" );
	    $text = $this->doc->createTextNode( $message );
	    $mess_obj->appendChild( $text );
	    $this->log->appendChild( $mess_obj );
	  }

	  public function close()
	  {
	    $this->doc->save( $this->fileName );
	  }
	}

	class TextLog
	{
	  private $fh;

	  public function TextLog( $fileName )
	  {
	    $this->fh = fopen( $fileName, "w" );
	  }
	  
	  public function add( $message )
	  {
	    fprintf( $this->fh, $message."\n" );
	  }

	  public function close()
	  {
	    fclose( $this->fh );
	  }
	}

	class Log
	{
	  private $xmlLog = null;
	  private $textLog = null;

	  public function Log()
	  {
	  }

	  public function start( $fileName )
	  {
	    $this->xmlLog = new XMLLog( $fileName.".xml" );
		$this->textLog = new TextLog( $fileName.".txt" );
	  }

	  public function add( $message )
	  {
		$this->xmlLog->add( $message );
		$this->textLog->add( $message );
	  }

	  public function end()
	  {
	    $this->xmlLog->close();
		$this->textLog->close();
	  }
	  
	  public static function instance()
	  {
	    static $inst = null;
		if ( !isset( $inst ) ) $inst = new Log();
		return $inst;
	  }
	}
	?>

7.11.2. Running the Hack

You run this hack from the command line using the PHP command-line interpreter:

	% php test.php
	% cat mylog.txt
	Opening application
	Logging a message
	Shutting down
	% cat mylog.xml
	<?xml version="1.0"?>
	<log>
	  <message>Opening application</message>
      <message>Logging a message</message>
	  <message>Shutting down</message>
	</log>

Not much to look at, but it's really the code (and not the output) we are interested in. Beginning with the test.php script, the code starts up the log, sends out a few messages, and then shuts down the log. It does that using only the three functions in the façade script, log.php. In fact, in an ideal environment, log.php is the only script that "outside" programmers would have access to.

The log.php file uses the Log singleton object [Hack #77] from the log_impl.php script to create two logs. It then sends each message to each log and has them output to the corresponding text or XML file.


Previous
Table of Contents
Next