模板方法模式 建造者模式 C++实现

May 13th, 2014 by JasonLe's Tech Leave a reply »

今天我继续来填坑,模板方法模式就是在模板方法中按照一定的规则顺序调用基本方法。这个比较简单。

比如我在父类run()中调用类中一系列的方法。钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。

Java中,如果父类里面有些方法不允许覆写,那么为了防止子类改变模板方法中的算法,可以将模板方法声明为final。

IMG_0432

比如下面函数中bool IsAlarm() 就是一个hook

#include <iostream>
using namespace std;

class CarTemplate
{
public:
	CarTemplate(void){};
    virtual ~CarTemplate(void){};

protected:
    virtual void Start() = 0;
    virtual void Stop() = 0;
    virtual void Alarm() = 0;
    virtual void EngineBoom() = 0;
    virtual bool IsAlarm() =0;

public:
    	void Run()
    	{
		Start();

		EngineBoom();

		if(IsAlarm())
			Alarm();

		Stop();
    	};
};

class Hummer: public CarTemplate
{
public:
	Hummer(){m_isAlarm = true;}
	virtual ~Hummer(){};

protected:
	void Start(){	cout<< "Hummer Start" <<endl;	}
	void Stop(){	cout<< "Hummer Stop" <<endl;	}
	void Alarm(){	cout<< "Hummer Alarm" <<endl;}
	bool IsAlarm(){	return m_isAlarm;		}
	void EngineBoom(){	cout<< "Hummer EngineBoom" <<endl;	}
private:
    bool m_isAlarm;
};

class Benz: public CarTemplate
{
public:
	Benz(){m_isAlarm = false;}
	virtual ~Benz(){};

protected:
	void Start(){	cout<< "Benz Start" <<endl;	}
	void Stop(){	cout<< "Benz Stop" <<endl;	}
	void Alarm(){	cout<< "Benz Alarm" <<endl;}
	bool IsAlarm(){	return m_isAlarm;		}
	void EngineBoom(){	cout<< "Benz EngineBoom" <<endl;	} 
private:     
        bool m_isAlarm; 
}; 
int main() 
{ 	
        CarTemplate *hummer = new Hummer(); 	
        hummer->Run();
	delete  hummer;

	CarTemplate *benz = new Benz();
	benz->Run();
	delete benz;
}

优点就在于可以封装不变的部分,拓展可变的部分,也就是把共性的东西抽取出来,这样可以便于维护。

但是缺点在于子类的执行,影响到父类的结果。有时候会有一些晦涩难懂。
———————————————————————————————-

在模板方法中,我们把相同的都封装在父类中,不同都定义在子类中。但是需求的变化是无穷无尽的。

比如建造的顺序可能是变化的,所以将他放到builder类中,通过builder类获取真正的product! 6446jgG

class Builder
{
public:
    virtual void BuildHead() {}
    virtual void BuildBody() {}
    virtual void BuildLeftArm(){}
    virtual void BuildRightArm() {}
    virtual void BuildLeftLeg() {}
    virtual void BuildRightLeg() {}
};
//构造瘦人
class ThinBuilder : public Builder
{
public:
    void BuildHead() { cout<<"build thin body"<<endl; }
    void BuildBody() { cout<<"build thin head"<<endl; }
    void BuildLeftArm() { cout<<"build thin leftarm"<<endl; }
    void BuildRightArm() { cout<<"build thin rightarm"<<endl; }
    void BuildLeftLeg() { cout<<"build thin leftleg"<<endl; }
    void BuildRightLeg() { cout<<"build thin rightleg"<<endl; }
};
//构造胖人
class FatBuilder : public Builder
{
public:
    void BuildHead() { cout<<"build fat body"<<endl; }
    void BuildBody() { cout<<"build fat head"<<endl; }
    void BuildLeftArm() { cout<<"build fat leftarm"<<endl; }
    void BuildRightArm() { cout<<"build fat rightarm"<<endl; }
    void BuildLeftLeg() { cout<<"build fat leftleg"<<endl; }
    void BuildRightLeg() { cout<<"build fat rightleg"<<endl; }   
};   //构造的指挥官   

class Director{   
private:   
      Builder *m_pBuilder;   
public:       
      Director(Builder *builder) { m_pBuilder = builder; }       
      void Create(){           
        m_pBuilder->BuildHead();
        m_pBuilder->BuildBody();
        m_pBuilder->BuildLeftArm();
        m_pBuilder->BuildRightArm();
        m_pBuilder->BuildLeftLeg();
        m_pBuilder->BuildRightLeg();
    }
};

int main()
{
    FatBuilder fat;
    Director director(&fat);
    director.Create();
---------------------------------------------------------------------------
    Builder *thin = new ThinBuilder();
    Director *dir = new Director(thin);
    dir->Create();

    return 0;
}

建造者模式的优点:在于我们不用关心每个产品内部的组成细节,比如FatBuildier ThinBuilider,然后我们交给Director来构造就好了。
建造者是独立的,我们可以拓展更多的builder完成不同的功能。并不对系统有任何影响。
特别适合产品类特别复杂,顺序不同,效能不同。顺序是区别模板模式与建造者模式最大的不同点!
另外同工厂模式进行比较,工厂模式适合生产零件。不能再细分了。否则就不适合工厂模式。

把模板方式和建造者模式组合起来可以产生很好的效果,可以按照model通过builder批量生产某种特定型号的产品。

IMG_0433

#include<iostream>
#include<vector>
#include<string>
using namespace std;

class CCarModel
{
public:
    CCarModel(void) {}
    virtual ~CCarModel(void){}
    void Run()
    {
    	    vector::const_iterator it = m_pSequence->begin();
	    for (; it < m_pSequence->end(); ++it)
	    {
	        string actionName = *it;
	        if(actionName.compare("start") == 0)
	        {
	            Start();
	        }
	        else if(actionName.compare("stop") == 0)
	        {
	            Stop();
	        }
	        else if(actionName.compare("alarm") == 0)
	        {
	            Alarm();
	        }
	        else if(actionName.compare("engine boom") == 0)
	        {
	            EngineBoom();
	        }
	    }
    }
    void SetSequence(vector *pSeq)
    {
    		m_pSequence = pSeq;
    }
protected:
    virtual void Start() = 0;
    virtual void Stop() = 0;
    virtual void Alarm() = 0;
    virtual void EngineBoom() = 0;
private:
    vector * m_pSequence;
};

class CBenzModel : public CCarModel
{
public:
    CBenzModel(void){}
    ~CBenzModel(void){}
protected:
    void Start(){cout << "Benz Start..." << endl;}
    void Stop(){cout << "Benz Stop..." << endl;}
    void Alarm(){cout << "Benz Alarm" << endl;}
    void EngineBoom(){cout << "Benz EngineBoom...." << endl;}
};

class CBMWModel : public CCarModel
{
public:
    CBMWModel(void){}
    ~CBMWModel(void){}
protected:
    void Start(){cout << "BMW Start..." << endl;}
    void Stop(){cout << "BMW Stop..." << endl;}
    void Alarm(){cout << "BMW Alarm" << endl;}
    void EngineBoom(){cout << "BMW EngineBoom...." << endl;}
};

class ICarBuilder
{
public:
    ICarBuilder(void)   { }
    virtual ~ICarBuilder(void)  { }
    virtual void SetSequence(vector *pseq) = 0;
    virtual CCarModel * GetCarModel() = 0;
};

class CBenzBuilder : public ICarBuilder
{
public:
    CBenzBuilder(void);
    ~CBenzBuilder(void);
    void SetSequence(vector *pSeq);
    CCarModel * GetCarModel();
private:
    CCarModel *m_pBenz;
};
CBenzBuilder::CBenzBuilder(void)
{
    m_pBenz = new CBenzModel();
}
CBenzBuilder::~CBenzBuilder(void)
{
    delete m_pBenz;
}
void CBenzBuilder::SetSequence(vector *pSeq)
{
    m_pBenz->SetSequence(pSeq);
}
CCarModel * CBenzBuilder::GetCarModel()
{
    return m_pBenz;
}

class CBMWBuilder :public ICarBuilder
{
public:
    CBMWBuilder(void);
    ~CBMWBuilder(void);
    void SetSequence(vector *pSeq);
    CCarModel * GetCarModel();
private:
    CCarModel *m_pBMW;
};

CBMWBuilder::CBMWBuilder(void)
{
    m_pBMW = new CBMWModel();
}
CBMWBuilder::~CBMWBuilder(void)
{
    delete m_pBMW;
}
void CBMWBuilder::SetSequence( vector *pSeq )
{
    m_pBMW->SetSequence(pSeq);
}
CCarModel * CBMWBuilder::GetCarModel()
{
    return m_pBMW;
}

class CDirector
{
public:
    CDirector(void);
    ~CDirector(void);
    CBenzModel * GetABenzModel();
    CBenzModel * GetBBenzModel();
    CBMWModel * GetCBMWModel();
    CBMWModel * GetDBMWModel();
private:
    vector * m_pSeqence;
    CBenzBuilder * m_pBenzBuilder;
    CBMWBuilder * m_pBMWBuilder;
};

CDirector::CDirector(void)
{
    m_pBenzBuilder = new CBenzBuilder();
    m_pBMWBuilder = new CBMWBuilder();
    m_pSeqence = new vector();
}
CDirector::~CDirector(void)
{
    delete m_pBenzBuilder;
    delete m_pBMWBuilder;
    delete m_pSeqence;
}
CBenzModel * CDirector::GetABenzModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBenzModel*>(m_pBenzBuilder->GetCarModel());
}
CBenzModel * CDirector::GetBBenzModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("engine boom");
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBenzModel*>(m_pBenzBuilder->GetCarModel());
}
CBMWModel * CDirector::GetCBMWModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("alarm");
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBMWBuilder->SetSequence(m_pSeqence);
    return static_cast<CBMWModel*>(m_pBMWBuilder->GetCarModel());
}
CBMWModel * CDirector::GetDBMWModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("start");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBMWModel*>(m_pBMWBuilder->GetCarModel());
}
int main(int argc, char const *argv[])
{
	CDirector *dir = new CDirector();

	dir->GetBBenzModel()->Run();
	return 0;
}

通过上面可以看出两个模式的配合得到了很好的运用!

引用 http://blog.csdn.net/wuzhekai1985/article/details/6667467