原型模式,模板方法模式
#原型模式
##一、UML图
关键词:深复制,Clone。
##二、概念
原型模式(Prototype):用原型示例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
##三、说明
(1)原型模式实际上就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
(2)一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,有对性能是大大的提高。因为如果不用Clone,每次new,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行这个初始化操作就实在是太低效了。
(3)浅复制和深复制:
浅复制:被复制的对象的所有变量都含有与原来的对象相同的值,而所有对其他对象的引用都仍然指向原来的对象。
深复制:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。
Clone的时候使用深复制。
##四、C++实现
(1)Prototype.h
//工作经验类:WorkExperience类
class WorkExperience
{
private:
std::string workDate;
std::string company;
public:
WorkExperience(){}
~WorkExperience(){}
//供克隆调用的构造函数
WorkExperience(WorkExperience* work)
{
this->workDate=work->workDate;
this->company=work->company;
}
std::string getWorkDate()
{
return workDate;
}
void setWorkDate(std::string workDate)
{
this->workDate=workDate;
}
std::string getCompany()
{
return company;
}
void setCompany(std::string company)
{
this->company=company;
}
//克隆
WorkExperience* Clone()
{
//调用供克隆调用的构造函数WorkExperience(WorkExperience)
return new WorkExperience(this);
}
};
//原型类,声明一个克隆自身的接口。
class Prototype
{
protected:
std::string name;
std::string sex;
std::string age;
std::string timeArea;
std::string company;
public:
virtual void SetPersonalInfo(std::string sex,std::string age)=0;
virtual void Display()=0;
virtual Prototype* Clone()=0;
};
//具体原型类,即ConcretePrototype类,本例中为简历Resume类,实现一个克隆自身的操作。
class Resume:public Prototype
{
private:
WorkExperience* work;
public:
Resume(std::string name)
{
this->name=name;
work=new WorkExperience();
}
~Resume()
{
if(work!=NULL)
delete work;
}
//供克隆调用的构造函数
Resume(WorkExperience* work)
{
this->work=work->Clone();
}
void SetPersonalInfo(std::string sex,std::string age)
{
this->sex=sex;
this->age=age;
}
void SetWorkExperience(std::string workDate,std::string company)
{
work->setWorkDate(workDate);
work->setCompany(company);
}
void Display()
{
std::cout<<name<<" "<<sex<<" "<<age<<std::endl;
std::cout<<"工作经历 "<<work->getWorkDate()<<" "<<work->getCompany()<<std::endl;
}
//克隆
Resume* Clone()
{
//调用 供克隆函数调用的构造函数Resume(work)
Resume *cloneResume=new Resume(work);
cloneResume->name=this->name;
cloneResume->age=this->age;
cloneResume->sex=this->sex;
return cloneResume;
}
};
(2).main.cpp
void main()
{
Resume* a=new Resume("大鸟");
a->SetPersonalInfo("男","29");
a->SetWorkExperience("1998-2000","XX公司");
Resume* b=a->Clone();
b->SetWorkExperience("1998-2006","YY公司");
Resume* c=b->Clone();
c->SetPersonalInfo("男","24");
c->SetWorkExperience("1998-2003","ZZ公司");
a->Display();
b->Display();
c->Display();
delete a;
delete b;
delete c;
a=b=c=NULL;
system("pause");
}
#模板方法模式
##一、UML图
关键词:骨架。
##二、概念
模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
##三、说明
角色:
(1)AbstractClass:是抽象类,其实也就是一个抽象模板,定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的框架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
(2)ConcreteClass:实现父类所定义的一个或多个抽象方法。每一个AbstractClass都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
总结:当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式,把这些行为搬移到单一的地方,这样帮助子类摆脱重复的不变行为的纠缠。
注意:在《大话设计模式》的例子中,AbstractClass为TestPaper类,ConcreteClass为TestPaperA和TestPaperB,而上述的UML图中的TemplateMethod()为TestQuestion1(),primitiveOperation1为函数Answer1(),primitiveOperation1为函数Answer2()等等。
四、C++实现
(1)TestPaper.h:
//AbstractClass,实现了一个模板,定义了算法的骨架,组成骨架的具体步骤放在子类中实现
class TestPaper
{
public:
void TestQuestion1()
{
std::cout<<"杨过得到,后来给了郭靖,练成倚天剑、屠龙刀的玄铁可能是【】a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维"<<std::endl;
std::cout<<"答案:"<<Answer1()<<std::endl;
}
void TestQuestion2()
{
std::cout<<"杨过、程英、陆无双铲除了情花,造成【】a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化"<<std::endl;
std::cout<<"答案:"<<Answer2()<<std::endl;
}
void TestQuestion3()
{
std::cout<<"蓝凤凰致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药【】a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量牛奶"<<std::endl;
std::cout<<"答案:"<<Answer3()<<std::endl;
}
protected:
virtual std::string Answer1()
{
return "";
}
virtual std::string Answer2()
{
return "";
}
virtual std::string Answer3()
{
return "";
}
};
//ConcreteClass,实现具体步骤
class TestPaperA:public TestPaper
{
protected:
virtual std::string Answer1()
{
return "b";
}
virtual std::string Answer2()
{
return "c";
}
virtual std::string Answer3()
{
return "a";
}
};
//ConcreteClass,实现具体步骤
class TestPaperB:public TestPaper
{
protected:
virtual std::string Answer1()
{
return "c";
}
virtual std::string Answer2()
{
return "a";
}
virtual std::string Answer3()
{
return "a";
}
};
(2).main.cpp
//Client,客户端
void main()
{
std::cout<<"学生甲抄的试卷:"<<std::endl;
TestPaper* studentA=new TestPaperA();
studentA->TestQuestion1();
studentA->TestQuestion2();
studentA->TestQuestion3();
std::cout<<std::endl;
std::cout<<"学生乙抄的试卷:"<<std::endl;
TestPaper* studentB=new TestPaperB();
studentB->TestQuestion1();
studentB->TestQuestion2();
studentB->TestQuestion3();
std::cout<<std::endl;
delete studentA;
delete studentB;
system("pause");
}
(3).运行结果
模板方法特点:
模板方法模式就是提供了一个很好的代码复用平台。通过把不变行为搬移到超类,去除子类中的重复代码来体现ta的优势。
当不变和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠