【设计模式】:对象创建型模式——1、Abstract Factory 抽象工厂

1、意图

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

2、别名

Kit

3、动机

考虑支持多视感的用户工具包,为保证风格可移植性,不应硬编码窗口组件
客户应仅与 WidegetFactory抽象类 交互,而不用具体类的接口

在这里插入图片描述

4、适用性

1、一个系统要独立于它的产品的创建、组合和表示时
2、 一个系统要由多个产品系列中的一个来配置时
3、当你要强调一系列相关的产品对象的设计,以便进行联合使用时
4、当你提供一个产品类库,而只想显示它们的接口而不是实现

5、结构

在这里插入图片描述

6、参与者

AbstractFactory【WidgetFactory 】
— 声明一个创建抽象产品对象的操作接口

ConcreteFactory【MotifWidgetFactory、PMWidgetFactory】
— 实现创建具体产品对象的操作

AbstractProduct【Windows、ScrollBar 】
— 为一类产品对象声明一个接口

ConcreteProduct【MotifWindow、MotifScrollBar】
— 定义一个将被相应的具体工厂创建的产品对象

Client
— 仅使用由 AbstractFactory 和 AbstractProduct 类声明的接口

7、协作

1、通常运行时创建一 ConcreteFactory 实例,此具体工厂创建特定的产品对象
为创建不同的产品对象,客户应使用不同的具体工厂

2、AbstractFactory 将产品创建延迟到其子类 ConcreteFactory

8、效果

优点:
1、它分离了具体的类
2、它使得易于交换产品系列
3、它有利于产品的一致性

缺点:
难以支持新种类的产品

9、实现

1、将工厂作为单例
2、创建产品【每个系列产品都要新具体工厂,多系列时 具体工厂也可用原型模式实现
3、定义可拓展的工厂【增新产品时,更灵活但不安全设计是创建操作增加参数
不安全本质:客户无法安全区分 抽象接口返回的产品类别

10、代码示例

maze_parts.h:

#pragma once
#include <memory>
#include <unordered_map>

enum class direction { north, east, south, west };

class map_site
{
public:
    virtual void enter() = 0;
};

class room : public map_site
{
public:
    room(int number):
        number_(number)
    {}

    int get_number()
    {
        return number_;
    }

    std::shared_ptr<map_site>
        get_side(direction dir) const
    {
        auto it = sides_.find(dir);
        return it == sides_.end() ? nullptr : it->second;
    }
    void set_side(direction dir, std::shared_ptr<map_site> site)
    {
        sides_[dir] = site;
    }

    virtual void enter() override
    {}

private:
    std::unordered_map<direction, std::shared_ptr<map_site>> sides_;
    int number_;
};

class wall : public map_site
{
public:
    virtual void enter() override
    {}
};

class door : public map_site
{
public:
    door(std::shared_ptr<room> room1, std::shared_ptr<room> room2)
    {
        room1_ = room1;
        room2_ = room2;
    }

    virtual void enter() override
    {}

    std::shared_ptr<room>
        other_side_from(std::shared_ptr<room> room)
    {
        if (room == room1_) return room2_;
        else if (room == room2_) return room1_;
        else return nullptr;
    }

private:
    std::shared_ptr<room> room1_;
    std::shared_ptr<room> room2_;
    bool is_open_;
};

class maze
{
public:
    void add_room(std::shared_ptr<room> item)
    {
        auto number = item->get_number();
        rooms_[number] = item;
    }

    std::shared_ptr<room> get_room(int number)
    {
        auto it = rooms_.find(number);
        return it == rooms_.end() ? nullptr : it->second;
    }

private:
    std::unordered_map<int, std::shared_ptr<room>> rooms_;
};

class bombed_wall : public wall
{
public:
    bombed_wall(bool bombed = false) :
        bomb_(bombed)
    {}

    virtual void enter() override
    {}

private:
    bool bomb_;
};

class room_with_a_bomb : public room
{
public:
    room_with_a_bomb(int number, bool bombed = false):
        room(number),
        bomb_(bombed)
    {}

    bool has_bomb() 
    {
        return bomb_;
    }

private:
    bool bomb_;
};

class spell
{};

class enchanted_room : public room
{
public:
    enchanted_room(int number, std::shared_ptr<spell> item = nullptr):
        room(number),
        spell_(item)
    {}

    bool has_spell()
    {
        return nullptr != spell_;
    }

    std::shared_ptr<spell> pick_up_spell()
    {
        return spell_;
    }

private:
    std::shared_ptr<spell> spell_;
};

class door_needing_spell : public door
{
public:
    door_needing_spell(std::shared_ptr<room> r1, std::shared_ptr<room> r2):
        door(r1, r2)
    {}
};

maze_factory.hpp:

#pragma once
#include "maze_parts.h"

class maze_factory
{
public:
    virtual std::shared_ptr<maze> make_maze() const
    {
        return std::make_shared<maze>();
    }
    virtual std::shared_ptr<wall> make_wall() const
    {
        return std::make_shared<wall>();
    }
    virtual std::shared_ptr<room> make_room(int n) const
    {
        return std::make_shared<room>(n);
    }
    virtual std::shared_ptr<door> make_door(std::shared_ptr<room> r1, std::shared_ptr<room> r2) const
    {
        return std::make_shared<door>(r1, r2);
    }
};

bombed_maze_factory.hpp:

#pragma once
#include "maze_factory.hpp"

class bombed_maze_factory : public maze_factory
{
public:
    std::shared_ptr<wall> make_wall() const override
    {
        return std::make_shared<bombed_wall>();
    }

    std::shared_ptr<room> make_room(int n) const override
    {
        return std::make_shared<room_with_a_bomb>(n);
    }
};

enchanted_maze_factory.hpp:

#pragma once
#include "maze_factory.hpp"

class enchanted_maze_factory : public maze_factory 
{
public:
    std::shared_ptr<room> make_room(int n)  const override
    {
        return std::make_shared<enchanted_room>(n, cast_spell());
    }

    std::shared_ptr<door> make_door(
        std::shared_ptr<room> r1, 
        std::shared_ptr<room> r2)  const override
    {
        return std::make_shared<door_needing_spell>(r1, r2);
    }

protected:
    std::shared_ptr<spell> cast_spell() const
    {
        return std::make_shared<spell>();
    }
};

maze_game.h:

#pragma once
#include "maze_factory.hpp"

class maze_game
{
public:
    std::shared_ptr<maze> create_maze(maze_factory& factory)
    {
        auto m = factory.make_maze();
        auto r1 = factory.make_room(1);
        auto r2 = factory.make_room(2);
        auto d = factory.make_door(r1, r2);

        m->add_room(r1);
        m->add_room(r2);

        r1->set_side(direction::north, factory.make_wall());
        r1->set_side(direction::east, d);
        r1->set_side(direction::south, factory.make_wall());
        r1->set_side(direction::west, factory.make_wall());

        r2->set_side(direction::north, factory.make_wall());
        r2->set_side(direction::east, factory.make_wall());
        r2->set_side(direction::south, factory.make_wall());
        r2->set_side(direction::west, d);

        return m;
    }
};

main.cpp:

#include <iostream>
#include "maze_game.h"
#include "bombed_maze_factory.hpp"
#include "enchanted_maze_factory.hpp"

int main()
{
    maze_game game;
    bombed_maze_factory factory;
    enchanted_maze_factory factory1;
    game.create_maze(factory1);
}
11、已知应用

1、InterView 定义 WidgetKit、DialogKit 生成对象;还用 LayoutKit 生成 不同组合对象
2、ET++[WGM88] 用 WindowSystem定义接口 [MakeWindow,MakeFont、MakeColor] 来创建各种窗口资源对象,达成系统间可移植性

10、相关模式

AbstractFactory 通常用 Factory Method [工厂方法]实现,也可用 Prototype [原型]实现
一个具体工厂通常是一个Singleton [单例]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值