在海贼世界中,位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族,当然了他们的逆向工程做的也很好,会拆船必然会造船。船是海贼们出海所必备的海上交通工具,它由很多的零件组成,从宏观上看它有这么几个组成部分:船体
、动力系统
、武器
。
根据这个表,在造船的时候需要根据不同的型号选择相应的零部件,在设计程序的时候还需要保证遵循开放-封闭原则,即添加了新型号之后不需要修改原有代码,而是添加新的代码。
假如我是一个客户,我在买船时我会根据自己手头资金来选择不同价位的型号,例如基础型、标准型、旗舰型,不同的型号下的船的组成采用不同的材料。
作为卖家,为了提高生产效率,我需要拆分出来不同的材料,最终根据型号打包在一起;比如对于船体来说,我拆分出来有木头,钢铁,合金,我在生产基础型号时,我就将木头,手动,枪打包在一起。
对于船体,动力,武器这三个组成部分来说,我们需要一个基类,然后在子类中去扩展;
船体代码
// 船体
class ShipBody
{
public:virtual string getShipBody() = 0;virtual ~ShipBody() {}
};class WoodBody : public ShipBody
{
public:string getShipBody() override{return string("用<木材>制作轮船船体...");}
};class IronBody : public ShipBody
{
public:string getShipBody() override{return string("用<钢铁>制作轮船船体...");}
};class MetalBody : public ShipBody
{
public:string getShipBody() override{return string("用<合金>制作轮船船体...");}
};
动力和武器
// 动力
class Engine
{
public:virtual string getEngine() = 0;virtual ~Engine() {}
};class Human : public Engine
{
public:string getEngine() override{return string("使用<人力驱动>...");}
};class Diesel : public Engine
{
public:string getEngine() override{return string("使用<内燃机驱动>...");}
};class Nuclear : public Engine
{
public:string getEngine() override{return string("使用<核能驱动>...");}
};// 武器
class Weapon
{
public:virtual string getWeapon() = 0;virtual ~Weapon() {}
};class Gun : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<枪>");}
};class Cannon : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<自动机关炮>");}
};class Laser : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<激光>");}
};
组装
// 轮船类
class Ship
{
public:Ship(ShipBody* body, Weapon* weapon, Engine* engine) :m_body(body), m_weapon(weapon), m_engine(engine) {}string getProperty(){string info = m_body->getShipBody() + m_weapon->getWeapon() + m_engine->getEngine();return info;}~Ship() {delete m_body;delete m_engine;delete m_weapon;}
private:ShipBody* m_body = nullptr;Weapon* m_weapon = nullptr;Engine* m_engine = nullptr;
};
整体代码
#include <iostream>
using namespace std;/**********************************_我需要定义三个船体结构的基类,以及各自的子类_**************************************/
/***********************_船体_**********************/
class shipBody
{
public:virtual ~shipBody() {} //虚析构是为了释放父类指针时能把子类对也释放掉virtual string getProperty() = 0;
};
class woodBody :public shipBody
{
public:woodBody() {}~woodBody() {}string getProperty(){return string("木质船身..");}
};
class ironBody :public shipBody
{
public:ironBody() {}~ironBody() {}string getProperty(){return string("钢铁船身..");}
};
class alloyBody :public shipBody
{
public:alloyBody() {}~alloyBody() {}string getProperty(){return string("合金船身..");}
};
/*******************************************************/
/***********************_动力_**********************/
class shipPower
{
public:virtual ~shipPower() {} //虚析构是为了释放父类指针时能把子类对也释放掉virtual string getProperty() = 0;
};
class humanPower :public shipPower
{
public:humanPower() {}~humanPower() {}string getProperty(){return string("手动驱动..");}
};
class nuclearPower :public shipPower
{
public:nuclearPower() {}~nuclearPower() {}string getProperty(){return string("核能驱动");}
};
class steamPower :public shipPower
{
public:steamPower() {}~steamPower() {}string getProperty(){return string("蒸汽驱动");}
};
/*******************************************************/
/***********************_武器_**********************/
class shipWeapon
{
public:virtual ~shipWeapon() {} //虚析构是为了释放父类指针时能把子类对也释放掉virtual string getProperty() = 0;
};
class gunWeapon :public shipWeapon
{
public:gunWeapon() {}~gunWeapon() {}string getProperty(){return string("枪支武器..");}
};
class artilleryWeapon :public shipWeapon
{
public:artilleryWeapon() {}~artilleryWeapon() {}string getProperty(){return string("火炮武器");}
};
class leaserWeapon :public shipWeapon
{
public:leaserWeapon() {}~leaserWeapon() {}string getProperty(){return string("激光武器");}
};
/*******************************************************/
/**********************************************************************************************************************/
/*****************************************************__船类__*********************************************************/
class ship
{
public:ship(shipBody* body,shipPower* power,shipWeapon* weapon):m_body(body),m_power(power),m_weapon(weapon){}string getProperty(){string info = m_body->getProperty() + m_power->getProperty() + m_weapon->getProperty();return info;}~ship(){delete m_body;delete m_power;delete m_weapon;}
private:shipBody* m_body = nullptr;shipPower* m_power = nullptr;shipWeapon* m_weapon = nullptr;
};
/***********************************************************************************************************************/
/*****************************************************__工厂类__**********************************************************/
class AbstractShipFactory
{
public:virtual ship* createShip() = 0;virtual ~AbstractShipFactory() {}
};class basicShip :public AbstractShipFactory
{
public:ship* createShip() override{ship* shipModel = new ship(new woodBody,new humanPower,new gunWeapon);cout << "<基础型>战船生成完毕,可以下水了...." << endl;return shipModel;}
};class standardShip :public AbstractShipFactory
{
public:ship* createShip() override{ship* shipModel = new ship(new ironBody, new steamPower, new artilleryWeapon);cout << "<标准型>战船生成完毕,可以下水了...." << endl;return shipModel;}
};class ultimateShip :public AbstractShipFactory
{
public:ship* createShip() override{ship* shipModel = new ship(new alloyBody, new nuclearPower, new leaserWeapon);cout << "<旗舰版>战船生成完毕,可以下水了...." << endl;return shipModel;}
};
/*************************************************************************************************************************/
int main()
{//造一艘旗舰版战船AbstractShipFactory* ultimateS = new ultimateShip;ship* s1 = ultimateS->createShip();cout << s1->getProperty() << endl;delete ultimateS;delete s1;AbstractShipFactory* basicS = new basicShip;ship* s2 = basicS->createShip();cout << s2->getProperty() << endl;;delete basicS;delete s2;//造一艘旗舰版战船AbstractShipFactory* standardS = new standardShip;ship* s3 = standardS->createShip();cout << s3->getProperty() <<endl;delete standardS;delete s3;return 0;
}