联系
Knight's Tale » 技术

Builder Design Pattern and Decorator Design Pattern (C++)

2010-07-14 21:37

This is a C++ project that describe the usage of  Builder Pattern design and Decorator Pattern design. The aim is to implement one task which is in the page 614 of ( Chinese version ).

File List:

  • Vocation.h :   Implement Decorator Pattern design
  • Vocation.cpp : Implement Decorator Pattern design
  • Builder.h : Implement Builder Pattern design
  • Builder.cpp : Implement Builder Pattern design
  • Test.cpp : a test driver
There are several important tips: 1. Java have memory garbage, but C++ don't have. So you should be careful when you use Decorator Pattern design. The trick is that you should write destructor for every decorator class. ( ex, VocationHotel, VocationTicket )

creatd by Knight 2010.07.14 www.liaoqiqi.com/blog

UML Chart:

Builder.h

#pragma once
#include "Vocation.h"
#include <iostream>
#include <vector>

using namespace DecoratorPatternDesign;
using namespace std;

namespace BuilderPatternDesgin
{
    //////////////////////////////////////////////////////////////////////////
    //
    // abstract builder
    //
    class AbstractBuilder
    {
    public:
        virtual void BuildDay(int dateId) = 0;
        virtual void AddHotel(string hotelName) =0;
        virtual void AddTickets(string ticketName)=0;
        virtual string GetVocationPlan()=0;
        virtual ~AbstractBuilder()=0{};
    };

    //////////////////////////////////////////////////////////////////////////
    //
    //
    //
    class VocationBuilder:public AbstractBuilder
    {
    public:
        VocationBuilder();
        ~VocationBuilder();
        void BuildDay(int dateId);
        void AddHotel(string hotelName);
        void AddTickets(string ticketName);
        string GetVocationPlan();

    private:
        vector vocation;
    };
}

Builder.cpp

#include "Builder.h"

namespace BuilderPatternDesgin
{
    VocationBuilder::VocationBuilder()
    {
        vocation.clear();
    }

    VocationBuilder::~VocationBuilder()
    {
        for(vector::iterator pos = vocation.begin();pos!=vocation.end();++pos)
        {
            if(*pos)
            {
                delete *pos;
                *pos = NULL;
            }
        }
    }

    void VocationBuilder::BuildDay(int dateId)
    {
        AbstractVocation *vocationNew = new VocationDate(dateId);
        vocation.push_back(vocationNew);
    }

    void VocationBuilder::AddHotel(string hotelName)
    {
        int dateSize = (int)vocation.size();
        vocation[dateSize-1] = new VocationHotel(vocation[dateSize-1],hotelName);
    }

    void VocationBuilder::AddTickets(string ticketName)
    {
        int dateSize = (int)vocation.size();
        vocation[dateSize-1] = new VocationTicket(vocation[dateSize-1],ticketName);
    }

    string VocationBuilder::GetVocationPlan()
    {
        string vocationList;
        for(vector::iterator pos = vocation.begin();pos!=vocation.end();++pos)
        {
            vocationList += ((*pos)->PlanList()) ;
            if((pos+1)!=vocation.end())
                vocationList += " ; ";
        }
        return vocationList;
    }
}

Vocation.h

#pragma once
#include <iostream>

using namespace std;

namespace DecoratorPatternDesign
{
    //////////////////////////////////////////////////////////////////////////
    //
    // Vocation class: the base class
    //
    class AbstractVocation
    {
    public:
        virtual string PlanList()= 0 { return "None";}
        virtual ~AbstractVocation()=0{};
    };

    //////////////////////////////////////////////////////////////////////////
    //
    // Concrete class: date
    //
    class VocationDate:public AbstractVocation
    {
    public:
        VocationDate(int dateId);
        string PlanList();

    private:
        int dateId;
    };

    //////////////////////////////////////////////////////////////////////////
    //
    // the decorator base class
    //

    class VocationActivity:public AbstractVocation
    {
        virtual string PlanList()=0;
    };

    //
    // hotel
    //
    class VocationHotel:public VocationActivity
    {
    public:
        VocationHotel(AbstractVocation* rhs,string hotelName);
        ~VocationHotel();
        string PlanList();

    private:
        string hotelName;
        AbstractVocation *vocation;
    };

    //
    // Ticket
    //
    class VocationTicket:public VocationActivity
    {
    public:
        VocationTicket(AbstractVocation* rhs,string ticketName);
        ~VocationTicket();
        string PlanList();

    private:
        string ticketName;
        AbstractVocation *vocation;
    };
}

Vocation.cpp

#include "Vocation.h"
using namespace std;
namespace DecoratorPatternDesign
{
    //////////////////////////////////////////////////////////////////////////
    //
    // Date
    //

    VocationDate:: VocationDate(int dateId)
    {
        this->dateId = dateId;
    };

    string VocationDate::PlanList()
    {
        string dateDesc = "Date: ";
        char dateIDStr[256];
        sprintf_s(dateIDStr,"%d",dateId);
        dateDesc += dateIDStr;
        return dateDesc;
    }

    //////////////////////////////////////////////////////////////////////////
    //
    // Hotel
    //

    VocationHotel::VocationHotel(AbstractVocation *rhs,string hotelName)
    {
        this->vocation = rhs;
        this->hotelName = hotelName;
    }

    VocationHotel::~VocationHotel()
    {
        if(vocation)
        {
            delete vocation;
            vocation =NULL;
        }
    }

    string VocationHotel::PlanList()
    {
        string planList = vocation->PlanList();
        planList+= " Hotel: " ;
        planList += hotelName;
        return planList;
    }

    //////////////////////////////////////////////////////////////////////////
    //
    // Ticket
    //

    VocationTicket::VocationTicket(AbstractVocation *rhs,string ticketName)
    {
        this->vocation = rhs;
        this->ticketName = ticketName;
    }

    VocationTicket::~VocationTicket()
    {
        if(vocation)
        {
            delete vocation;
            vocation =NULL;
        }
    }

    string VocationTicket::PlanList()
    {
        string planList = vocation->PlanList();
        planList+= " Ticket: " ;
        planList += ticketName;
        return planList;
    }
}

Test.cpp

#include "Builder.h"
#include <iostream>
#include <string>

using namespace std;
using namespace BuilderPatternDesgin;

void main()
{
    VocationBuilder builder;

    // the first day
    builder.BuildDay(1);
    builder.AddHotel("H 1");
    builder.AddTickets("T 1");
    std::cout << builder.GetVocationPlan() <<std::endl;

    // the second day
    builder.BuildDay(2);
    builder.AddHotel("H 2");
    builder.AddTickets("T 2");
    std::cout << builder.GetVocationPlan() <<std::endl;

    // the third day
    builder.BuildDay(3);
    builder.AddHotel("H 3");
    std::cout << builder.GetVocationPlan() <<std::endl;
}

Results: