Object Oriented Programming Patterns for Geeks
The Facade Pattern
namespace ooppatterns
{
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main( string[] args )
{
// the facade object - used to make the
// order process it wraps easier to use
OrderProcessor SC = new OrderProcessor();
if ( !SC.PlaceOrder( "Matt", "Haujobb", 2 ) )
Console.WriteLine( "Order could not be sent!" );
Console.WriteLine( new string( '-', 50 ) );
if ( !SC.PlaceOrder( "Bob", "Fight Club", 3 ) )
Console.WriteLine( "Order could not be sent!" );
Console.WriteLine( new string( '-', 50 ) );
if ( !SC.PlaceOrder( "Mick", "Aladin", 1 ) )
Console.WriteLine( "Order could not be sent!" );
Console.WriteLine( new string( '-', 50 ) );
if ( !SC.PlaceOrder( "Andy", "Haujobb", 2 ) )
Console.WriteLine( "Order could not be sent!" );
Console.ReadLine();
}
}
// The facade (or wrapper)
class OrderProcessor
{
// The objects the facade is wrapping
private StockRoom _SR = new StockRoom();
private Accounts _AC = new Accounts();
private Delivery _DE = new Delivery();
// A simplified method...
public bool PlaceOrder( string customer, string product, int units )
{
// the more complicated process...
if ( this._SR.CanFullfillOrder( product, units ) )
{
item order = this._SR.RequestItem( product, units );
order.costInPence += this._DE.DeliveryCost( order );
this._AC.ChargeCustomer( customer, order );
this._DE.Dispatch( customer, product, order );
return true;
}
else
{
Console.WriteLine( "Stock room had insufficient stock" );
return false;
}
}
}
// The following objects represent the subsystem(s)...
class item
{
public int unitsInStock;
public int costInPence;
public item( int unitsInStock, int costInPence )
{
this.unitsInStock = unitsInStock;
this.costInPence = costInPence;
}
}
class StockRoom
{
private Dictionary<string, item> _stock = new Dictionary<string, item>();
// pretend this data is sourced from a DB...
public StockRoom()
{
this._stock.Add( "Haujobb", new item( 3, 1000 ) );
this._stock.Add( "Fight Club", new item( 2, 1200 ) );
this._stock.Add( "Aladin", new item( 4, 800 ) );
}
public bool CanFullfillOrder( string product, int units )
{
Console.WriteLine( "Checking stock of {0}.", product );
if ( !this._stock.ContainsKey( product ) )
return false;
return this._stock[product].unitsInStock >= units;
}
public item RequestItem( string product, int units )
{
if ( !this._stock.ContainsKey( product ) )
return null;
if ( this._stock[product].unitsInStock >= units )
{
item prod = this._stock[product];
item retVal = new item( units, prod.costInPence * units );
prod.unitsInStock -= units;
Console.WriteLine( "Stock room has picked order of {0} x {1}. " +
@"There are {2} units left in stock.", units, product, prod.unitsInStock );
return retVal;
}
else
return null;
}
}
class Accounts
{
public void ChargeCustomer( string customer, item order )
{
Console.WriteLine( "Customer '{0}' has been charged {1} pence.",
customer, order.costInPence );
}
}
class Delivery
{
public int DeliveryCost( item order )
{
int postage = order.unitsInStock * 45;
Console.WriteLine( "Postage for {0} units is {1}.", order.unitsInStock,
postage );
return postage;
}
public void Dispatch( string customer, string product, item order )
{
Console.WriteLine( "{0} x {1} units at {2} has been dispatched to {3}.",
product, order.unitsInStock, order.costInPence, customer );
}
}
}