SDSU CS 696: Advanced OO
Spring Semester, 1997
Doc 12, Abstract Factory and Bridge

To Lecture Notes Index
San Diego State University -- This page last updated Mar 20, 1997
----------

Contents of Doc 12, Abstract Factory and Bridge


Abstract Factory slide # 2
...How Do Factories create Widgets slide # 6
......Method 1) My Factory Method slide # 6
......Method 2) Their Factory Method slide # 7
......Method 3) Prototype slide # 9
...Applicability slide # 10
...Consequences slide # 10
Bridge Pattern slide # 12
...Applicability slide # 14
...Consequences slide # 14

Doc 12, Abstract Factory and Bridge Slide # 1

Abstract Factory

Example - Write a CrossPlatform Window Toolkit

Write a toolkit to allow applications with GUI interfaces to run on multiple platforms (Mac, PC, OS/2, Unix motif ) using the look and feel of each platform

We will look at widgets: Windows, Menu's and Buttons

Create an interface( or abstract class) for each widget and an concrete class for each platform:




Doc 12, Abstract Factory and Bridge Slide # 2
This allows the application to write to the widget interface

public void installDisneyMenu()
     {
     Menu disney = create a menu somehow
     disney.addItem( "Disney World" );
     disney.addItem( "Donald Duck" );
     disney.addItem( "Mickey Mouse" );
     disney.addGrayBar( );
     disney.addItem( "Minnie Mouse" );
     disney.addItem( "Pluto" );
     etc.
     }

How to create the widget?


Doc 12, Abstract Factory and Bridge Slide # 3
Use Abstract Factory

abstract class WidgetFactory
     {
     public Window createWindow();
     public Menu createMenu();
     public Button createButton();
     }
     
class MacWidgetFactory extends WidgetFactory
     {
     public Window createWindow() 
          { code to create a mac window }
          
     public Menu createMenu() 
          { code to create a mac Menu }
          
     public Button createButton() 
          { code to create a mac button }
     }     

class Win95WidgetFactory extends WidgetFactory
     {
     public Window createWindow() 
          { code to create a Win95 window }
          
     public Menu createMenu() 
          { code to create a Win95 Menu }
          
     public Button createButton() 
          { code to create a Win95 button }
     }
Etc.

Doc 12, Abstract Factory and Bridge Slide # 4
Now to get code that works for all platforms we get:

public void installDisneyMenu(WidgetFactory myFactory)
     {
     Menu disney = myFactory.createMenu();
     disney.addItem( "Disnsey World" );
     disney.addItem( "Donald Duck" );
     disney.addItem( "Mickey Mouse" );
     disney.addGrayBar( );
     disney.addItem( "Minnie Mouse" );
     disney.addItem( "Pluto" );
     etc.
     }

We just need to make sure that the application for each platform creates the proper factory

Doc 12, Abstract Factory and Bridge Slide # 5

How Do Factories create Widgets?

Method 1) My Factory Method


abstract class WidgetFactory
     {
     public Window createWindow();
     public Menu createMenu();
     public Button createButton();
     }
     
class MacWidgetFactory extends WidgetFactory
     {
     public Window createWindow() 
          { return new MacWidow() }
          
     public Menu createMenu() 
          { return new MacMenu() }
          
     public Button createButton() 
          { return new MacButton()  }
     }     


Doc 12, Abstract Factory and Bridge Slide # 6
How Do Factories create Widgets?

Method 2) Their Factory Method


abstract class WidgetFactory
     {
     private Window windowFactory;
     private Menu menuFactory;
     private Button buttonFactory;

     public Window createWindow()
          { return windowFactory.createWindow() }

     public Menu createMenu();
          { return menuFactory.createWindow() }

     public Button createButton()
          { return buttonFactory.createWindow() }

     }
     
class MacWidgetFactory extends WidgetFactory
     {
     public MacWidgetFactory()
          {
          windowFactory = new MacWindow();
          menuFactory = new MacMenu();
          buttonFactory = new MacButton();
          }
     }     

class MacWindow extends Window
     {
     public Window createWindow() { blah }
     etc.

Doc 12, Abstract Factory and Bridge Slide # 7
How Do Factories create Widgets?
Method 2) Their Factory Method
When does this make Sense?

There might be more than one way to create a widget

abstract class WidgetFactory
     {
     private Window windowFactory;
     private Menu menuFactory;
     private Button buttonFactory;

     public Window createWindow()
          { return windowFactory.createWindow() }

     public Window createWindow( Rectangle size)
          { return windowFactory.createWindow( size ) }

     public Window createWindow( Rectangle size, String title)
          { return windowFactory.createWindow( size, title) }

     public Window createFancyWindow()
          { return windowFactory.createFancyWindow() }

     public Window createPlainWindow()
          { return windowFactory.createPlainWindow() }

Using factory method allows abstract class to do all the different ways to create a window.

Subclasses just provide the objects windowFactory, menuFactory, buttonFactory, etc.


Doc 12, Abstract Factory and Bridge Slide # 8
How Do Factories create Widgets?

Method 3) Prototype


class WidgetFactory
     {
     private Window windowPrototype;
     private Menu menuPrototype;
     private Button buttonPrototype;

     public WidgetFactory( Window windowPrototype,
                              Menu menuPrototype,
                              Button buttonPrototype)
          {
          this.windowPrototype = windowPrototype;
          this.menuPrototype = menuPrototype;
          this.buttonPrototype = buttonPrototype;
          }

     public Window createWindow()
          { return windowFactory.createWindow() }

     public Window createWindow( Rectangle size)
          { return windowFactory.createWindow( size ) }

     public Window createWindow( Rectangle size, String title)
          { return windowFactory.createWindow( size, title) }

     public Window createFancyWindow()
          { return windowFactory.createFancyWindow() }

etc.

There is no need for subclasses of WidgetFactory.

Doc 12, Abstract Factory and Bridge Slide # 9

Applicability



Consequences


Implementation


Doc 12, Abstract Factory and Bridge Slide # 10
Problem: Cheating Application Code

public void installDisneyMenu(WidgetFactory myFactory)
     {
     // We ship next week, I can't get the stupid generic Menu to 
     // do the fancy Mac menu stuff
     // Windows version won't ship for 6 months
     // Will fix this later

     MacMenu disney = (MacMenu) myFactory.createMenu();
     disney.addItem( "Disney World" );
     disney.addItem( "Donald Duck" );
     disney.addItem( "Mickey Mouse" );
     disney.addMacGrayBar( );
     disney.addItem( "Minnie Mouse" );
     disney.addItem( "Pluto" );
     etc.
     }


Doc 12, Abstract Factory and Bridge Slide # 11

Solution: Bridge Pattern




class Window
     {
     private WindowImp realWindow;
     
     public void hide()          { realWindow.hide(); }

     public void show()          { realWindow.show();}

etc.


Doc 12, Abstract Factory and Bridge Slide # 12
Not all Window Methods need be one line

public void drawRectangle(int upperLeftX, int upperLeftY, 
                         int lowerRightX, int lowerRightY)
     {
     realWindow.drawLine( upperLeftX, upperLeftY,
                               lowerRightX, upperLeftY);
     realWindow.drawLine( lowerRightX, upperLeftY, 
                              lowerRightX, lowerRightY);
     realWindow.drawLine( lowerRightX, lowerRightY, 
                              upperLeftX, lowerRightY);
     realWindow.drawLine( upperLeftX, lowerRightY, 
                              upperLeftX, upperLeftY);
     }
}


Application Code can't Cheat

Client code (application) has access to Window objects

Window object can't be cast to another type!


Doc 12, Abstract Factory and Bridge Slide # 13

Applicability


Use the Bridge pattern when

Consequences



To create a button the Java source code in the Button class does:

peer = getToolkit().createButton();

Java's AWT classes then have method like:

public void setColor( Color newColor )
     {
     peer.setColor( newColor );
     }




----------