Приглашаем посетить
Пушкин (pushkin-lit.ru)

Hack 73. Write Portable Code with Bridges

Previous
Table of Contents
Next

Hack 73. Write Portable Code with Bridges

Hack 73. Write Portable Code with Bridges Hack 73. Write Portable Code with Bridges

Use a Bridge pattern to hide the implementation on an object, or to change the implementation based on the environment.

In one of my jobs, working for a company that shipped a very large cross-platform C++ application, we used the heck out of the Bridge pattern. The Bridge pattern allows you to hide a portion of the implementation of a class in another class, either because you want to hide the code from other implementers or because the implementation of a portion of the code is platform specific.

I've taken the platform-specific approach in this hack to show the benefits of a bridge. Figure 7-7 shows the relationship between two classes, TableCreator and TableCreatorImp. The role of the table creator is to create tables in the target database. The implementation class, TableCreatorImp, is defined in another file, which is included from a database-specific directory.

This flexibility allows for one version of the code specific to Oracle and another for MySQL (or any other database). This is handy, as each database has a different syntax for creating tables.

Figure 7-7. The TableCreator class and its implementation class
Hack 73. Write Portable Code with Bridges


7.8.1. The Code

Save the code in Example 7-7 as bridge.php.

Example 7-7. The base Bridge pattern class
	<?php
	require( "sql.php" );

	class TableCreator
	{
	  static function createTable( $name )
	  {
	    TableCreatorImp::createTable( $name );
	  }
	}

	TableCreator::createTable( "customer" );
	?>

Save the code in Example 7-8 as mysql/sql.php.

Example 7-8. An example implementation class for MySQL
	<?php
	class TableCreatorImp
	{
	  static public function createTable( $name )
	  {
	    echo( "MySQL version of createTable for $name\n" );
	  }
	}
	?>

Save the code in Example 7-9 as oracle/sql.php.

Example 7-9. An example implementation for Oracle
	<?php
	class TableCreatorImp
	{
	  static public function createTable( $name )
	  {
		echo( "Oracle version of createTable for $name\n" );
	  }
	}
	?>

7.8.2. Running the Hack

Running this code requires some extra command-line parameters, instructing the PHP interpreter to include either the mysql or oracle directory in the include path (and therefore using that database-specific bridge). Here is the version using the MySQL code:

	% php -d include_path='.:/usr/local/php5/lib/php:mysql' bridge.php
	MySQL version of createTable for customer

Here is the version using the Oracle code:

	% php -d include_path='.:/usr/local/php5/lib/php:oracle' bridge.php
	Oracle version of createTable for customer

It's not rocket science, so you should get the idea pretty quickly. TableCreator actually is implemented by one of several versions of TableCreatorImp, located in platform-specific directories.

Obviously the code here does not create tables; this is merely a framework that would need some additional code to actually work. But the specifics of building tables in different databases aren't germane to teaching the Bridge pattern (that's fancy talk for "You can figure that out on your own").

One big drawback of bridges is that you can't extend your implementation-specific classes. In this case, this isn't an issue, as all the methods in the implementation classes are static. But for regular objects with nonstatic methods, the implementation class derives from the base nonimplementation class. For example, CButtonImp derives from CButton. To extend the behavior, the code would need to derive from CButtonImp, which is hidden. Arguably, however, this is more of a problem in compiled languages like C++.


Previous
Table of Contents
Next