// Sandwich.h: interface for the Sandwich class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_SANDWICH_H__675D6587_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_SANDWICH_H__675D6587_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 typedef double Amount; #include <string> using std::string; class Sandwich { public: virtual ~Sandwich(); virtual Amount getPrice() = 0; virtual string getName() = 0; protected: Sandwich(); }; #endif // !defined(AFX_SANDWICH_H__675D6587_481A_11D3_BA98_00500428 B24D__INCLUDED_) // SandwichDecorator.h: interface for the SandwichDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_SANDWICHDECORATOR_H__675D658A_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_SANDWICHDECORATOR_H__675D658A_481A_11D3_BA98_00500428 B24D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "Sandwich.h" #include "NullSandwich.h" class SandwichDecorator : public Sandwich { public: virtual ~SandwichDecorator(); protected: SandwichDecorator(Sandwich* sandwich); inline Sandwich& getSandwich(); inline virtual string getName(); inline virtual Amount getPrice(); private: SandwichDecorator(const SandwichDecorator& sd); //disable Sandwich* m_sandwich; }; inline Sandwich& SandwichDecorator::getSandwich() { static NullSandwich ns; // return either the wrapped sandwich or the null sandwich (if 0) return (m_sandwich) ? *m_sandwich : ns ; } inline string SandwichDecorator::getName() { return getSandwich().getName(); } inline Amount SandwichDecorator::getPrice() { return getSandwich().getPrice(); } #endif // !defined(AFX_SANDWICHDECORATOR_H__675D658A_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // BasicHamburger.h: interface for the BasicHamburger class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_BASICHAMBURGER_H__675D658B_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_BASICHAMBURGER_H__675D658B_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "Sandwich.h" class BasicHamburger : public Sandwich { public: BasicHamburger(); virtual ~BasicHamburger(); inline virtual Amount getPrice(); inline virtual string getName(); }; inline string BasicHamburger::getName() { return "Hamburger"; } inline Amount BasicHamburger::getPrice() { // current price - here for now - future calc return 1.79; } #endif // !defined(AFX_BASICHAMBURGER_H__675D658B_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // BasicHamburger.cpp: implementation of the BasicHamburger class. // /////////////////////////////////////////////////////////////////// #include "BasicHamburger.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// BasicHamburger::BasicHamburger() { } BasicHamburger::~BasicHamburger() { } // BaconDecorator.h: interface for the BaconDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_BACONDECORATOR_H__675D6590_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_BACONDECORATOR_H__675D6590_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class BaconDecorator : public SandwichDecorator { public: BaconDecorator(Sandwich* sandwich); virtual ~BaconDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string BaconDecorator::getName() { return getSandwich().getName() + ", bacon"; } inline Amount BaconDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + .50; } #endif // !defined(AFX_BACONDECORATOR_H__675D6590_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // BaconDecorator.cpp: implementation of the BaconDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "BaconDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// BaconDecorator::BaconDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } BaconDecorator::~BaconDecorator() { } // /////////////////////////////////////////////////////////////////// #if !defined(AFX_CHEESEDECORATOR_H__675D6594_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_CHEESEDECORATOR_H__675D6594_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class CheeseDecorator : public SandwichDecorator { public: CheeseDecorator(Sandwich* sandwich); virtual ~CheeseDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string CheeseDecorator::getName() { return getSandwich().getName() + ", cheese"; } inline Amount CheeseDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + .30; } #endif // !defined(AFX_CHEESEDECORATOR_H__675D6594_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // CheeseDecorator.cpp: implementation of the CheeseDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CheeseDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// CheeseDecorator::CheeseDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } CheeseDecorator::~CheeseDecorator() { } // KetchupDecorator.h: interface for the KetchupDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_KETCHUPDECORATOR_H__675D6591_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_KETCHUPDECORATOR_H__675D6591_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class KetchupDecorator : public SandwichDecorator { public: KetchupDecorator(Sandwich* sandwich); virtual ~KetchupDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string KetchupDecorator::getName() { return getSandwich().getName() + ", ketchup"; } inline Amount KetchupDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + 0.0; } #endif // !defined(AFX_KETCHUPDECORATOR_H__675D6591_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // KetchupDecorator.cpp: implementation of the KetchupDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "KetchupDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// KetchupDecorator::KetchupDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } KetchupDecorator::~KetchupDecorator() { } // LettuceDecorator.h: interface for the LettuceDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_LETTUCEDECORATOR_H__675D658E_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_LETTUCEDECORATOR_H__675D658E_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class LettuceDecorator : public SandwichDecorator { public: LettuceDecorator(Sandwich* sandwich); virtual ~LettuceDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string LettuceDecorator::getName() { return getSandwich().getName() + ", lettuce"; } inline Amount LettuceDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + 0.0; } #endif // !defined(AFX_LETTUCEDECORATOR_H__675D658E_481A_11D3_BA98_ 8_00500428B24D__INCLUDED_) // LettuceDecorator.cpp: implementation of the // LettuceDecorator class // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "LettuceDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// LettuceDecorator::LettuceDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } LettuceDecorator::~LettuceDecorator() { } // MayonnaiseDecorator.h: interface for the // MayonnaiseDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_MAYONNAISEDECORATOR_H__675D658F_481A_11D3_ BA98_00500428B24D__INCLUDED_) #define AFX_MAYONNAISEDECORATOR_H__675D658F_481A_11D3_BA98_0050 0428B24D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class MayonnaiseDecorator : public SandwichDecorator { public: MayonnaiseDecorator(Sandwich* sandwich); virtual ~MayonnaiseDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string MayonnaiseDecorator::getName() { return getSandwich().getName() + ", mayonnaise"; } inline Amount MayonnaiseDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + 0.0; } #endif // !defined(AFX_MAYONNAISEDECORATOR_H__675D658F_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // MayonnaiseDecorator.cpp: implementation of the // MayonnaiseDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "MayonnaiseDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// MayonnaiseDecorator::MayonnaiseDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } MayonnaiseDecorator::~MayonnaiseDecorator() { } // NullSandwich.h: interface for the NullSandwich class.
[1] So what is this NullSandwich? It doesn't sound too filling, does it? Basically one common observation in programming is that testing the result of an operation for an exception value is time consuming. Basically the Null Pattern (by Bobby Woolf published in PLoP 3, March, 1997) encapsulates this exception value as a separate class (or instance) of the type that handles all operations as you would want the exception value to handle. Most commonly, the behavior is to do nothing. This significantly simplifies the client, avoiding the need to test for special-case tests usually at the cost of one extra subclass per interface. This Null Object is normally implemented as a Singleton [Gam, 95] or a Flyweight [Gam, 95] and often is combined with other patterns.
// /////////////////////////////////////////////////////////////////// #if !defined(AFX_NULLSANDWICH_H__675D6595_481A_11D3_BA98_00
500428B24D__INCLUDED_) #define AFX_NULLSANDWICH_H__675D6595_481A_11D3_BA98_00500428 B24D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "Sandwich.h" class NullSandwich : public Sandwich { public: NullSandwich(); virtual ~NullSandwich(); inline virtual Amount getPrice(); inline virtual string getName(); }; inline Amount NullSandwich::getPrice() { return 0.0; } inline string NullSandwich::getName() { return "Nothing"; } #endif // !defined(AFX_NULLSANDWICH_H__675D6595_481A_11D3_BA98_00 500428B24D__INCLUDED_) // NullSandwich.cpp: implementation of the NullSandwich class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "NullSandwich.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// NullSandwich::NullSandwich() { } NullSandwich::~NullSandwich() { } // OnionDecorator.h: interface for the OnionDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_ONIONDECORATOR_H__675D658C_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_ONIONDECORATOR_H__675D658C_481A_11D3_BA98_00500428 B24D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class OnionDecorator: public SandwichDecorator { public: OnionDecorator(Sandwich* sandwich); virtual ~OnionDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string OnionDecorator::getName() { return getSandwich().getName() + ", onion"; } inline Amount OnionDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + 0.0; } #endif // !defined(AFX_ONIONDECORATOR_H__675D658C_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // OnionDecorator.cpp: implementation of the OnionDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "OnionDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// OnionDecorator::OnionDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } OnionDecorator::~OnionDecorator() { } // SalsaDecorator.h: interface for the SalsaDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_SALSADECORATOR_H__675D6592_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_SALSADECORATOR_H__675D6592_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class SalsaDecorator : public SandwichDecorator { public: SalsaDecorator(Sandwich* sandwich); virtual ~SalsaDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string SalsaDecorator::getName() { return getSandwich().getName() + ", salsa"; } inline Amount SalsaDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + 0.0; } #endif // !defined(AFX_SALSADECORATOR_H__675D6592_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // SalsaDecorator.cpp: implementation of the SalsaDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "SalsaDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// SalsaDecorator::SalsaDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } SalsaDecorator::~SalsaDecorator() { } // TomatoDecorator.h: interface for the TomatoDecorator class. // /////////////////////////////////////////////////////////////////// #if !defined(AFX_TOMATODECORATOR_H__675D658D_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_TOMATODECORATOR_H__675D658D_481A_11D3_BA98_00500428B24D__ INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" class TomatoDecorator : public SandwichDecorator { public: TomatoDecorator(Sandwich* sandwich); virtual ~TomatoDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); }; inline string TomatoDecorator::getName() { return getSandwich().getName() + ", tomato"; } inline Amount TomatoDecorator::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + 0.0; } #endif // !defined(AFX_TOMATODECORATOR_H__675D658D_481A_11D3_BA98_ 00500428B24D__INCLUDED_) // TomatoDecorator.cpp: implementation of the TomatoDecorator class. // /////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "TomatoDecorator.h" /////////////////////////////////////////////////////////////////// // Construction/Destruction /////////////////////////////////////////////////////////////////// TomatoDecorator::TomatoDecorator(Sandwich* sandwich): SandwichDecorator(sandwich) { } TomatoDecorator::~TomatoDecorator() { } Main // BurgerLand.cpp : Defines the entry point for the console application. // #include <iostream> #include <memory> #include "Sandwich.h" #include "CheeseDecorator.h" #include "BaconDecorator.h" #include "TomatoDecorator.h" #include "BasicHamburger.h" int main(int argc, char* argv[]) { Sandwich* sand = new CheeseDecorator(new BaconDecorator(new TomatoDecorator(new BasicHamburger))); std::cout << sand->getName() << " price = $" << sand->getPrice(); delete sand; return 0; }
Following is an example of a simple template definition to avoid coding the many classes:
///////////////////////////////////////////////////////////// // TSandwichDecorator.h: interface for the Standard Template Decorator class. ///////////////////////////////////////////////////////////// #if !defined(AFX_TSANDWICHDECORATOR_H__675D6594_481A_11D3_BA98_ 00500428B24D__INCLUDED_) #define AFX_TSANDWICHDECORATOR_H__675D6594_481A_11D3_BA98_00500428 B24D__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "SandwichDecorator.h" template <const Amount price> class TSandwichDecorator : public SandwichDecorator { public: inline TSandwichDecorator(const string& name, Sandwich* sandwich); inline virtual ~TSandwichDecorator(); inline virtual string getName(); inline virtual Amount getPrice(); private: const string m_name; }; template <const Amount price> inline TSandwichDecorator<price>::TSandwichDecorator(const string& name, Sandwich* sandwich): SandwichDecorator(sandwich), m_name(name) { } template <const Amount price> inline TSandwichDecorator<price>::~TSandwichDecorator() { } template <const Amount price> inline string TSandwichDecorator<price>::getName() { return getSandwich().getName() + ", " + m_name; } template <const Amount price> inline Amount TSandwichDecorator<price>::getPrice() { // current price - here for now - future calc return getSandwich().getPrice() + price; } #endif // !defined(AFX_TSANDWICHDECORATOR_H__675D6594_481A_11D3_BA98_ 00500428B24D__INCLUDED_)
This could then be used as follows:
// BurgerLandWithTemplate.cpp : Defines the entry point for the console application. // #include <iostream> #include <memory> #include "Sandwich.h" #include "CheeseDecorator.h" #include "BaconDecorator.h" #include "TomatoDecorator.h" #include "BasicHamburger.h" #include "TSandwichDecorator.h" static const string cheddarName = "Cheddar Cheese"; typedef TSandwichDecorator<.50> CheddarCheeseDecorator; int main(int argc, char* argv[]) { Sandwich* sand = new CheeseDecorator(new BaconDecorator(new TomatoDecorator(new CheddarCheeseDecorator(cheddarName, new BasicHamburger)))); std::cout << sand->getName() << " price = $" << sand->getPrice(); delete sand; return 0; }
3.144.17.91