网站开发作业代做,企业手机网站建设公司,建设厅网站查询资质,如何给网站添加外链1. 奔向大海
在海贼世界中#xff0c;位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族#xff0c;当然了他们的逆向工程做的也很好#xff0c;会拆船必然会造船。船是海贼们出海所必备的海上交通工具#xff0c;它由很多的零件组成#xff0c;从宏观上看…1. 奔向大海
在海贼世界中位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族当然了他们的逆向工程做的也很好会拆船必然会造船。船是海贼们出海所必备的海上交通工具它由很多的零件组成从宏观上看它有这么几个组成部分船体、动力系统、武器。
有一天我攒够了钱要出海找到了弗兰奇一家发现他们的老大跟着草帽路飞出海了但是我还是选择相信他们的技术。下面是他们给我制定的造船方案根据我的购买力提供了不同型号的海贼船一共是三个级别如下表
基础型标准型旗舰型船体木头钢铁合成金属动力手动内燃机核能武器枪速射炮激光
根据这个表在造船的时候需要根据不同的型号选择相应的零部件在设计程序的时候还需要保证遵循开放-封闭原则即添加了新型号之后不需要修改原有代码而是添加新的代码。
1.1 船体
因为要建造的这艘船是由多个部件组成的并且每个部件还有不同的品级可供选择先说船体关于船体材料的这个属性是可变的所以还需要给它提供一个抽象类这样在这个抽象类的子类中就可以更换不同的船体材料了
// 船体
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(用合金制作轮船船体...);}
};这样只要添加了新的造船材料就给它添加一个对应的子类父类是 ShipBody在这个子类重写父类的虚函数getShipBody()用这种材料把船体造出来就行了。
1.2 动力和武器
知道了如何处理船体部分那么动力和武器部分的处理思路也是一样的
可以给船提供不同的动力系统因此这个属性是可变的所以需要提供一个抽象类可以给船提供不同的武器系统因此这个属性也是可变的所以也需要提供一个抽象类
照葫芦画瓢把代码写一下
// 动力
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(配备的武器是激光);}
};不论是动力还是武器系统都是需要提供一个抽象类这样它们的子类就可以基于这个抽象基类进行专门定制如果要对它们进行拓展也只需添加新的类不需要修改原有代码。
1.3 一艘船
如果有了以上的零件只需要在工厂中将它们装配到一起这样就得到了一艘船这是一艘什么型号的船取决于使用的是什么零件所以只需要让这艘船对应一个类就可以了这个类的定义如下
// 轮船类
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;
};这艘船使用的零件是通过构造函数参数传递进来的并在类的内部对这些零件对象进行了保存这样在释放船这个对象的时候就可以将相应的零件对象一并析构了。
另外在Ship这个类中保存零件对象的时候使用的是它们的父类指针这样就可以实现多态了。
2. 准备生产
万事俱备只剩建厂了。造船厂要生产三种型号的船那么也就是至少需要三条生产线所以对应的工厂类也就不止一个处理思路还是一样的提供一个抽象的基类然后在它的子类中完成各种型号的船的组装每个子类对应的就是一条生产线。
2.1 设计图纸
现在关于抽象工厂模式的逻辑应该是比较清晰了下面来看一下这个模式对应的UML类图 在这个图中有四个抽象类分别是
ShipBody 类船体的抽象类 有三个子类在子类中通过不同的材料来建造船体Weapon 类武器的抽象类 有三个子类在子类中给战船提供不同种类的武器Engine 类动力系统抽象类 有三个子类在子类中给战船提供不同动力系统AbstractFactory 类抽象工厂类 在子工厂类中生产不同型号的战船 和ShipBody 、Weapon、Engine有依赖关系在工厂函数中创建了它们的实例对象 和Ship 类有依赖关系在工厂函数中创建了它的实例对象
关于Ship类它可以和ShipBody 、Weapon、Engine可以是聚合关系也可以是组合关系
组合关系析构Ship类对象的时候也释放了ShipBody 、Weapon、Engine对象聚合关系析构Ship类对象的时候没有释放ShipBody 、Weapon、Engine对象 在上面的Ship类的析构函数中做了释放操作因此在UML中将它们之间描述为了组合关系。
在使用抽象工厂模式来处理实际问题的时候由于实际需求不一样我们画出的UML类图中有些类和类之间的关系可能也会有所不同所以上图只适用于当前的业务场景在处理其他需求的时候还需要具体问题具体分析。
2.2 开工
给上面的程序再添加相应的工厂类就可以生产出我们需要的型号的船只了示例代码如下
#include iostream
#include string
using namespace std;// 船体
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 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 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 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;
};// 工厂类
class AbstractFactory
{
public:virtual Ship* createShip() 0;virtual ~AbstractFactory() {}
};class BasicFactory : public AbstractFactory
{
public:Ship* createShip() override{Ship* ship new Ship(new WoodBody, new Gun, new Human);cout 基础型战船生产完毕, 可以下水啦... endl;return ship;}
};class StandardFactory : public AbstractFactory
{
public:Ship* createShip() override{Ship* ship new Ship(new IronBody, new Cannon, new Diesel);cout 标准型战船生产完毕, 可以下水啦... endl;return ship;}
};class UltimateFactory : public AbstractFactory
{
public:Ship* createShip() override{Ship* ship new Ship(new MetalBody, new Laser, new Nuclear);cout 旗舰型战船生产完毕, 可以下水啦... endl;return ship;}
};int main()
{AbstractFactory* factroy new StandardFactory;Ship* ship factroy-createShip();cout ship-getProperty();delete ship;delete factroy;return 0;
}在main()函数中要通过工厂类的工厂函数生产什么型号的战船和用户的需求息息相关所以这个选择也是用户通过客户端的操作界面做出的在这个例子中关于客户端的界面操作就直接忽略了。
抽象工厂模式适用于比较复杂的多变的业务场景总体上就是给一系列功能相同但是属性会发生变化的组件如船体材料、武器系统、动力系统添加一个抽象类这样就可以非常方便地进行后续的拓展再搭配工厂类就可以创建出我们需要的对象了。
关于简单工厂模式、工厂模式和抽象工厂模式的区别可以做如下总结
简单工厂模式不能遵守开放-封闭原则工厂和抽象工厂模式可以简单工厂模式只有一个工厂类工厂和抽象工厂有多个工厂类工厂模式创建的产品对象相对简单抽象工厂模式创建的产品对象相对复杂 工厂模式创建的对象对应的类不需要提供抽象类【这产品类组件中没有可变因素】 抽象工厂模式创建的对象对应的类有抽象的基类【这个产品类组件中有可变因素】