抽象工厂模式(Abstract Factory)

  GOF:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

  类图:

  


 

  

  观察类图,关键就在于左边,即AbstractFactory和它的两个子类。想要理解这个模式,我们可以真的将它看作一个工厂。对于生产家电的工厂,一般要生产电视和洗衣机,但是在美国的家电工厂生产的是等离子电视和全自动洗衣机,在非洲的家电工厂生产的是CRT彩电和半自动洗衣机。把这个例子转换成类似上面的类图就如下:

  这时,如果想要开工厂,就能从彩电工厂生产标准知道彩电工厂能生产电视和洗衣机,然后根据你在哪个国家来具体决定彩电工厂的类型。

 

  AbstractFactory一般是抽象类(但不是绝对的),它定义了必需的接口,而具体接口的实现放到了子类。用户只需知道Factory中有什么接口就行了,剩下就交给多态吧(在设计模式中,很多巧妙的地方就是靠多态实现的)。

  比如:一群学生要去参观家电工厂的生产过程,则代码如下:

void StudentVisit(AbstractFactory& factory) {

    factory.MakeTV();

    factory.MakeWasher();

}



int main() {

    USAFactory factory;

    StudentVisit(factory);

    

    return 0;

}

  这里实际传入的参数是美国家电工厂,则实际调用的是美国家电工厂的MakeTV()和MakeWasher()。

 

  适用性:

  • 一个系统要独立于它的产品的创建,组合和表示时。(我们只需要知道有什么接口,而不需要了解子类是怎么实现的)
  • 一个系统要由多个产品系列中的一个来配置时。(比如上面电视有多种,但是美国彩电工厂要的是等离子电视)
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。(彩电工厂需要生产电视和洗衣机,这两个就是相关的产品)
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。(我们只需要调用抽象类的接口,而不需要到子类中看具体的方法)

   优点 + 缺点:

  • 它分离了具体的类。
  • 它使得易于交换产品系列。改变使用的具体工厂就能生产不同的产品。
  • 它有利于产品的一致性。每一个具体工厂生产的都是同一等级的产品。
  • 难以支持新种类的产品。如果要在抽象类中增加接口,每个具体工厂都要进行修改。

 


 

  最后以一个创建游戏场景的例子结束,该游戏场景会产生地形,光源,植被。

  类图:

  代码:

  先看看Product,即类图右边的类:

  地形类:

class Terrain {

public:

    virtual string GetType() const = 0;

};



class DesertTerrain : public Terrain {

public:

    DesertTerrain() {

        m_type = "Desert";

    }

    string GetType() const {

        return m_type;

    }

private:

    string m_type;

};



class MountainTerrain : public Terrain {

public:

    MountainTerrain() {

        m_type = "Mountain";

    }

    string GetType() const {

        return m_type;

    }

private:

    string m_type;

};

  光源类:

class Light {

public:

    virtual string GetType() const = 0;

};



class SpotLight : public Light{

public:

    SpotLight() {

        m_type = "Spot Light";

    }

    string GetType() const {

        return m_type;

    }

private:

    string m_type;

};



class DirectionLight : public Light {

public:

    DirectionLight() {

        m_type = "Direction Light";

    }

    string GetType() const {

        return m_type;

    }

private:

    string m_type;

};

  植被类:

class Plant {

public:

    virtual string GetType() const = 0;

};



class TreePlant : public Plant {

public:

    TreePlant() {

        m_type = "Tree";

    }

    string GetType() const {

        return m_type;

    }

private:

    string m_type;

};



class CactusPlant : public Plant {

public:

    CactusPlant() {

        m_type = "Cactus";

    }

    string GetType() const {

        return m_type;

    }

private:

    string m_type;

};

  

 以下就看工厂类:

class GameSceneFactory {

public:



    virtual Terrain* MakeTerrain() const = 0;

    virtual Light* MakeLight() const = 0;

    virtual Plant* MakePlant() const = 0;

};



class DesertSceneFactory : public GameSceneFactory {

public:



    Terrain* MakeTerrain() const {

        return new DesertTerrain();

    }



    Light* MakeLight() const {

        return new DirectionLight();

    }



    Plant* MakePlant() const {

        return new CactusPlant();

    }

};



class MountainSceneFactory : public GameSceneFactory {

public:



    Terrain* MakeTerrain() const {

        return new MountainTerrain();

    }



    Light* MakeLight() const {

        return new SpotLight();

    }



    Plant* MakePlant() const {

        return new TreePlant();

    }

};

  以下就是具体的使用:

class Game {

public:

    void createScene(GameSceneFactory& factory) {

        m_terrain = factory.MakeTerrain();

        m_light = factory.MakeLight();

        m_plant = factory.MakePlant();

        print();

    }

    void print() {

        cout << "------Game Scene------" << endl;

        cout << "Terrain: " << m_terrain->GetType() << endl;

        cout << "Light: " << m_light->GetType() << endl;

        cout << "Plant: " << m_plant->GetType() << endl;

    }

private:

    Terrain* m_terrain;

    Light* m_light;

    Plant* m_plant;

};



int main() {

    Game game;

    MountainSceneFactory factory;

    game.createScene(factory);

}

  结果:

 


  小结:抽象工厂模式是一个比较常用的模式,需要好好掌握。利用真实生活中的工厂就比较好理解该模式的运作,但真正要掌握还得在日常编码中的适当场合使用。

  

你可能感兴趣的:(abstract)