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 [单例]