|

This sample code provides a real-world example of how to use the decorator pattern. The sample code is spread over four (4) files: gambler.h, gamblers.cpp, decorators.cpp, and main.cpp.
// Decorator pattern sample code in C++
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: gambler.h
Contains: - Gambler, GamblerDecorator, GamblerWithCar class definitions
------------------------------------------------------------ */
#include <iostream>
#define ODD 1
#define EVEN 0
using namespace std;
class Gambler
{
public:
// member functions
Gambler();
// Default constructor
// Pre-conditions: None
// Post-conditions: Gambler constructed
Gambler(Gambler* newGambler);
// Constructor - constucts a new gambler, needed for use of the decorator
// Pre-conditions: newGambler is a valid gambler
// Post-conditions: an identical gambler is constructed
void placeBet(bool on, long amount);
// stores information of the bet placed by the player
// Pre-conditions: valid input parameters
// Post-conditions: information about next bet is stored
void checkWinning(bool result);
// checks the bet information and confirm a win or lost
// Pre-conditions: bet information is up to date
// Post-conditions: balance and state is updated accordingly
virtual void specialOps();
// special operations the gambler can perform according to his state
void addBalance(long addition);
// changes balance of the gambler according to the input
// Pre-conditions: none
// Post-conditions: Balance is updated to balance + addition
long getBalance();
// Pre-conditions: none
// Post-conditions: balance of the gambler is returned
bool hasCar();
// Pre-conditions: none
// Post-contitions: returns true of gambler has a car
private:
// variables
long balance; // current balance of the gambler
long betAmount; // amount of money for next bet
bool betOn; // odd or even
bool haveCar; // true if gambler has a car
};
class GamblerDecorator : public Gambler
{
// abstract decorator for gambler - adds functionality to specialOps()
public:
// member functions
GamblerDecorator();
// Default Constructor
// Pre-conditions: none
// Post-conditions: an abstract decorator is constructed
GamblerDecorator(Gambler* newGambler);
// Constructor
// Pre-conditions: none
// Post-conditions: an abstract decorator is constructed for newGamblre
virtual void specialOps() = 0;
// virtual function
// must be inplemented by concrete decorators
};
class GamblerWithCar : public GamblerDecorator
{
// concrete decorator - adds responsibility to specialOps()
public:
// member funcitons
GamblerWithCar();
// Default Constructor
// Pre-conditions: none
// Post-conditions: an concrete decorator is constructed
GamblerWithCar(Gambler* newGambler);
// Constructor
// Pre-conditions: none
// Post-conditions: an concrete decorator is constructed for newGamblre
void specialOps();
// Gambler::specialOps() is called. New functionality of souping up your car is added
// Pre-conditions: none
// Post-conditions: special operation performed
void newOps();
// newFunctionality only when gambler has a car
// Pre-conditions: none
// Post-conditions: car is souped up according to user input
private:
// variables
double pimpFactor; // how pimping your ride is
};
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: gamblers.cpp
Contains: - Gamble class implementations
------------------------------------------------------------ */
#include "gambler.h"
Gambler::Gambler()
// Default constructor
// Pre-conditions: None
// Post-conditions: Gambler constructed
{
balance = 5000;
haveCar = false;
}
Gambler::Gambler(Gambler* newGambler)
// Constructor - constucts a new gambler, needed for use of the decorator
// Pre-conditions: newGambler is a valid gambler
// Post-conditions: an identical gambler is constructed
{
balance = newGambler->getBalance();
haveCar = newGambler->hasCar();
}
void Gambler::placeBet(bool on, long amount)
// stores information of the bet placed by the player
// Pre-conditions: valid input parameters
// Post-conditions: information about next bet is stored
{
betAmount = amount;
betOn = on;
}
void Gambler::checkWinning(bool result)
// checks the bet information and confirm a win or lost
// Pre-conditions: bet information is up to date
// Post-conditions: balance and state is updated accordingly
{
if (betOn == result)
{
balance += betAmount;
cout << "\nYou won!!" << endl;
}
else
{
balance -= betAmount;
cout << "\nYou lost!!" << endl;
}
}
void Gambler::specialOps()
// special operations the gambler can perform according to his state
{
int choice;
if (!haveCar)
{
cout << "Do you want to buy a car [1 = Yes / 2 = No]? ->";
cin >> choice;
if (choice == 1)
{
if(balance > 25000)
{
haveCar = true;
addBalance(-20000);
cout << "You just bought a PIMPmobile!!" << endl;
}
else
{
cout << "Your don't have enough money!!" << endl;
}
}
}
else
{
cout << "Driving around is fun" << endl;
}
}
void Gambler::addBalance(long addition)
// changes balance of the gambler according to the input
// Pre-conditions: none
// Post-conditions: Balance is updated to balance + addition
{
balance += addition;
}
long Gambler::getBalance()
// Pre-conditions: none
// Post-conditions: balance of the gambler is returned
{
return balance;
}
bool Gambler::hasCar()
// Pre-conditions: none
// Post-contitions: returns true of gambler has a car
{
return haveCar;
}
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: decorators.cpp
Contains: - GamblerDecorator, GamblerWithCar class implementations
------------------------------------------------------------ */
#include "gambler.h"
GamblerDecorator::GamblerDecorator()
// Default Constructor
// Pre-conditions: none
// Post-conditions: an abstract decorator is constructed
{
}
GamblerDecorator::GamblerDecorator(Gambler* newGambler) : Gambler(newGambler)
// Constructor
// Pre-conditions: none
// Post-conditions: an abstract decorator is constructed for newGamblre
{
}
GamblerWithCar::GamblerWithCar()
// Default Constructor
// Pre-conditions: none
// Post-conditions: an concrete decorator is constructed
{
pimpFactor = 0;
}
GamblerWithCar::GamblerWithCar(Gambler* newGambler) : GamblerDecorator(newGambler)
// Constructor
// Pre-conditions: none
// Post-conditions: an concrete decorator is constructed for newGamblre
{
pimpFactor = 0;
}
void GamblerWithCar::specialOps()
// Gambler::specialOps() is called. New functionality of souping up your car is added
// Pre-conditions: none
// Post-conditions: special operation performed
{
int choice, amount;
Gambler::specialOps();
newOps();
}
void GamblerWithCar::newOps()
// newFunctionality only when gambler has a car
// Pre-conditions: none
// Post-conditions: car is souped up according to user input
{
int choice, amount;
cout << "\nYour current PIMP factor is " << pimpFactor << endl;
cout << "Want to spend some money souping up your car [1 = Yes / 2 = No]? ->";
cin >> choice;
if (choice == 1)
{
cout << "How much do you want to spend? ->";
cin >> amount;
Gambler::addBalance((-1)*amount);
pimpFactor += amount / (314.159);
cout << "Your new PIMP factor is " << pimpFactor << endl;
}
}
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: main.cpp
Contains: - driver program to demonstrate decorator
------------------------------------------------------------ */
#include <stdlib.h>
#include <time.h>
#include "gambler.h"
using namespace std;
int main()
{
Gambler* myGambler = new Gambler();
bool done = false;
char choiceChar;
int choice, temp;
bool ownCar = false;
long amount;
srand(time(NULL));
cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
cout << "$$ Welcome to the Happy Happy Joy Joy Casino $$" << endl;
cout << "$$ - where your money is as good as ours - $$" << endl;
cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
while(!done)
{
if(myGambler->hasCar()&&!ownCar)
{
// if a gambler buys a car for the first time
myGambler = new GamblerWithCar(myGambler);
ownCar = true;
}
cout << "\nWhat would you like to do?" << endl;
cout << "1. Place a bet 2. Something special 3. Quit ->";
cin >> choiceChar;
choice = atoi(&choiceChar);
switch (choice)
{
case 1:
{
cout << "\nYou currently have $" << myGambler->getBalance() << endl;
cout << "How much would you like to bet? ->";
cin >> amount;
cout << "1. Even 2. Odd ->";
cin >> choice;
if ((choice == 1)||(choice == 2))
{
myGambler->placeBet((choice-1),amount);
temp = rand()%2;
myGambler->checkWinning(temp);
}
else
cout << "Invalid selection!" << endl;
break;
}
case 2:
{
myGambler->specialOps();
break;
}
case 3:
{
done = true;
break;
}
default:
{
break;
}
}
}
return 0;
}

This sample code provides a real-world example of how to use the decorator pattern. The sample code is spread over four (4) files: Gambler.java, GamblerWithCar.java, GamblerDecorator.java, and Main.java.
// Decorator pattern sample code in Java
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: Gambler.java
Contains: - Gambler class implementation
------------------------------------------------------------ */
package gamblingOnlyDecorator;
import java.io.DataInputStream;
import java.io.IOException;
class Gambler
{
private final int ODD = 1;
private final int EVEN = 0;
private final long RICH = 25000;
private final long POOR = 0;
private final long NORMAL = 5000;
boolean haveCar;
long balance;
long betAmount;
int currentState;
boolean betOn;
Gambler()
// Default constructor
// Pre-conditions: None
// Post-conditions: Gambler constructed
{
balance = 5000;
haveCar = false;
}
Gambler(Gambler newGambler)
// Constructor - constucts a new gambler, needed for use of the decorator
// Pre-conditions: newGambler is a valid gambler
// Post-conditions: An identical gambler is constructed
{
balance = newGambler.getBalance();
haveCar = newGambler.hasCar();
}
void placeBet(boolean on, long amount)
// stores information of the bet placed by the player
// Pre-conditions: Valid input parameters
// Post-conditions: Information about next bet is stored
{
betAmount = amount;
betOn = on;
}
void checkWinning(boolean result)
// checks the bet information and confirm a win or lost
// Pre-conditions: Bet information is up to date
// Post-conditions: Balance is updated accordingly
{
if (betOn == result)
{
balance += betAmount;
System.out.println("\nYou won!!\n");
}
else
{
balance -= betAmount;
System.out.println("\nYou lost!!\n");
}
}
void specialOps()
// Special operations the gambler can perform
{
int choice = 0;
if (!haveCar)
{
System.out.println("Do you want to buy a car [1 = Yes / 2 = No]? ->\n");
DataInputStream in = new DataInputStream(System.in);
try { choice = Integer.parseInt(in.readLine()); }
catch (NumberFormatException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
if (choice == 1)
{
if(balance > 25000)
{
haveCar = true;
addBalance(-20000);
System.out.println("You just bought a PIMPmobile!!\n");
}
else
{
System.out.println("You don't have enough money!!\n");
}
}
}
else
{
System.out.println("Driving around is fun\n");
}
}
void addBalance(long addition)
// changes balance of the gambler according to the input
// Pre-conditions: None
// Post-conditions: Balance is updated to balance + addition
{
balance += addition;
}
long getBalance()
// Pre-conditions: None
// Post-conditions: Balance of the gambler is returned
{
return balance;
}
boolean hasCar()
// Pre-conditions: None
// Post-contitions: Returns true if gambler has a car
{
return haveCar;
}
}
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: GamblerWithCar.java
Contains: - GamblerWithCar class implementations
------------------------------------------------------------ */
package gamblingOnlyDecorator;
import java.io.DataInputStream;
import java.io.IOException;
class GamblerWithCar extends GamblerDecorator
{
private double pimpFactor;
GamblerWithCar()
// Default Constructor
// Pre-conditions: none
// Post-conditions: an concrete decorator is constructed
{
pimpFactor = 0;
}
GamblerWithCar(Gambler newGambler)
// Constructor
// Pre-conditions: none
// Post-conditions: an concrete decorator is constructed for newGambler
{
pimpFactor = 0;
}
void specialOps()
// Gambler.specialOps() is called. New functionality of souping up your car is added
// Pre-conditions: none
// Post-conditions: car souped up according to user input
{
int choice = 0, amount = 0;
specialOps();
System.out.println("\nYour current PIMP factor is " + pimpFactor + "\n");
System.out.println("Want to spend some money souping up your car [1 = Yes / 2 = No]? ->\n");
DataInputStream in = new DataInputStream(System.in);
try { choice = Integer.parseInt(in.readLine()); }
catch (NumberFormatException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
if (choice == 1)
{
System.out.println("How much do you want to spend? ->\n");
try { amount = Integer.parseInt(in.readLine()); }
catch (NumberFormatException e1) { e1.printStackTrace(); }
catch (IOException e1) { e1.printStackTrace(); }
addBalance((-1)*amount);
pimpFactor += amount / (314.159);
System.out.println("Your new PIMP factor is " + pimpFactor + "\n");
}
}
};
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: GamblerDecorator.java
Contains: - GamblerDecorator class implementations
------------------------------------------------------------ */
package gamblingOnlyDecorator;
abstract class GamblerDecorator extends Gambler
{
protected Gambler gambler;
public GamblerDecorator()
// Default Constructor
// Pre-conditions: none
// Post-conditions: an abstract decorator is constructed
{
}
public GamblerDecorator(Gambler newGambler)
// Constructor
// Pre-conditions: none
// Post-conditions: an abstract decorator is constructed for newGambler
{
}
abstract void specialOps();
}
/* ---------------------------------------------------------
Group: three-ten Software
Members: Rory Hansen
Binh Ho
Ivan Sham
Soo Wei Tan
Date: January 31, 2004
File Name: Main.java
Contains: - driver program to demostrate decorator pattern
------------------------------------------------------------ */
package gamblingOnlyDecorator;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Random;
class Main
{
public static void main(String[] args) throws IOException
{
String owner;
int choice = 0;
int temp;
boolean result = false;
boolean done = false;
boolean ownCar = false;
long amount = 0;
Gambler myGambler = new Gambler();
DataInputStream in = new DataInputStream(System.in);
Random randomNumberGenerator = new Random();
System.out.println(" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n" );
System.out.println(" $$ Welcome to the Happy Happy Joy Joy Casino $$\n" );
System.out.println(" $$ - where your money is as good as ours - $$\n" );
System.out.println(" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n" );
while (done != true)
{
if (myGambler.hasCar() && !ownCar)
{
myGambler = new GamblerWithCar(myGambler);
ownCar = true;
}
System.out.println("\nWhat would you like to do?\n");
System.out.println("1. Place a bet 2. Something special 3. Quit ->");
try
{ choice = Integer.parseInt(in.readLine()); }
catch (NumberFormatException e) { e.printStackTrace();}
catch (IOException e) { e.printStackTrace(); }
switch (choice)
{
case 1:
{
System.out.println("\nYou currently have $" + myGambler.getBalance() + "\n");
System.out.println("How much would you like to bet? ->");
try
{ amount = Integer.parseInt(in.readLine()); }
catch (NumberFormatException e) { e.printStackTrace();}
catch (IOException e) { e.printStackTrace(); }
System.out.println("1. Even 2. Odd ->");
try
{ choice = Integer.parseInt(in.readLine()); }
catch (NumberFormatException e) { e.printStackTrace();}
catch (IOException e) { e.printStackTrace(); }
if ((choice == 1)||(choice == 2))
{
boolean on;
if (choice == 1)
{ on = false; }
else
{ on = true; }
myGambler.placeBet(on, amount);
temp = (randomNumberGenerator.nextInt())%2;
if (temp == 1)
{ result = false; }
else
{ result = true; }
myGambler.checkWinning(result);
}
else
System.out.println("Invalid selection!\n");
break;
}
case 2:
{
myGambler.specialOps();
break;
}
case 3:
{
done = true;
break;
}
default:
break;
}
}
}
}
|