小菜準備面試,打印了多份一模一樣的簡歷。大鳥看代碼發現:main() 中三次 new Resume 並逐字段 SetPersonalInfo、SetWorkExperience。若需 20 份,不僅代碼冗長,一處錯誤還需改 20 次。
class Resume {
public:
Resume(char* _name) : name(_name), sex(0), age(0), timeArea(0), company(0) {}
void SetPersonalInfo(char* _sex, char* _age) { sex = _sex; age = _age; }
void SetWorkExperience(char* _timeArea, char* _company) { timeArea = _timeArea; company = _company; }
void Display() { printf("%s %s %s 工作經歷:%s %s", name, sex, age, timeArea, company); }
private:
char *name, *sex, *age, *timeArea, *company;
};
int main() {
Resume a("大鳥"); a.SetPersonalInfo("男","29"); a.SetWorkExperience("1998-2000","XX公司");
Resume b("大鳥"); b.SetPersonalInfo("男","29"); b.SetWorkExperience("1998-2000","XX公司");
Resume c("大鳥"); c.SetPersonalInfo("男","29"); c.SetWorkExperience("1998-2000","XX公司");
a.Display(); b.Display(); c.Display();
}
用一個原型實例指定創建對象的種類,並通過複製這個原型來創建新對象。避免了繁瑣的初始化,支援動態增減產品類,無需固定繼承體系。
缺點:每個類需實現克隆方法。

class ICloneable {
public:
virtual ICloneable* Clone() = 0;
};
class WorkExperience : public ICloneable {
public:
char*& WorkDate() { return workDate; }
char*& Company() { return company; }
WorkExperience* Clone() override {
auto* result = new WorkExperience();
result->WorkDate() = workDate;
result->Company() = company;
return result;
}
private:
char *workDate, *company;
};
class Resume : public ICloneable {
public:
Resume(char* _name) : name(_name), work(new WorkExperience()) {}
~Resume() { delete work; }
void SetPersonalInfo(char* _sex, char* _age) { sex = _sex; age = _age; }
void SetWorkExperience(char* _workDate, char* _company) {
work->WorkDate() = _workDate;
work->Company() = _company;
}
void Display() { printf("%s %s %s 工作經歷:%s %s", name, sex, age, work->WorkDate(), work->Company()); }
Resume* Clone() override {
auto* result = new Resume(name); // 注意:此處原碼有誤,應傳 name 而非 work
result->name = name;
result->sex = sex;
result->age = age;
result->work = work->Clone(); // 深拷貝工作經歷
return result;
}
private:
char *name, *sex, *age;
WorkExperience* work;
};
int main() {
Resume* proto = new Resume("大鳥");
proto->SetPersonalInfo("男", "29");
proto->SetWorkExperience("1998-2000", "XX公司");
Resume* a = proto->Clone();
Resume* b = proto->Clone();
Resume* c = proto->Clone();
a->Display(); b->Display(); c->Display();
// 清理內存...
}
WorkExperience 指標必須深拷貝,否則多份簡歷共享同一工作經歷對象,修改其一會影響其它。PrototypeManager 註冊/查找原型,進一步解耦客戶端與具體類。從「手寫 N 份簡歷」到「克隆 1 份原型」,原型模式讓對象創建變得優雅高效。