资源和工厂设计模式薄弱
Weak resources and factory design pattern
想出一种如何最好地处理以下设计(伪C++代码(的方法:
class Display {
public:
Bitmap GetBitmap(uint16 width, uint16 height);
private:
// A list of active bitmaps
std::set<Bitmap> bitmaps;
}
。其中 Display 是位图对象的工厂(和唯一所有者(。Display 还必须跟踪std::set
容器内所有分配的位图,并可能随时选择使其失效/删除(例如在全屏切换中(。
因此,从本质上讲,位图是一个弱资源句柄,无论谁持有该句柄,都必须在使用它之前检查它是否有效。
我现在的理论解决方案是使用C++智能指针:
-
GetBitmap()
将返回一个weak_ptr<Bitmap>
,因此可以使用weakBitmap.lock()
检查有效性。 - 内部位图std::set容器将保存
shared_ptr<Bitmap>
以便能够释放弱位图指针。
实现给定设计的最佳方法是什么?对于我缺少的给定功能,是否存在事实上的设计模式?
我认为您可能需要考虑扭转局面:放弃您创建的对象的所有权(例如返回boost::shared_ptr<Bitmap>
(,只保留指向内部集合中对象的弱指针(例如 std::list<boost::weak_ptr<Bitmap>>
(。每当用户请求位图时,请锁定集合并在那里添加新的位图。如果您的集合是一个列表,则可以安全地将迭代器存储到仅添加的元素,并在以后将其从集合中删除,从而处理位图的销毁。
由于boost::shared_ptr::lock
是原子的,因此在多线程时也可以工作。但是您仍然需要用锁保护对收藏的访问。
下面是示例代码:
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
class Display;
class Bitmap : boost::noncopyable
{
friend class Display;
Bitmap(int, Display* d) : display(d)
{}
Display* display;
public:
~Bitmap(); // see below for definition
};
typedef boost::shared_ptr<Bitmap> BitmapPtr;
class Display
{
typedef std::list<boost::weak_ptr<Bitmap>> bitmaps_t;
typedef std::map<Bitmap*, bitmaps_t::iterator> bitmap_map_t;
bitmaps_t bitmaps_;
bitmap_map_t bitmap_map_;
boost::mutex mutex_;
friend class Bitmap;
void Remove(Bitmap* p)
{
boost::lock_guard<boost::mutex> g(mutex_);
bitmap_map_t::iterator i = bitmap_map_.find(p);
if (i != bitmap_map_.end())
{
bitmaps_.erase(i->second);
bitmap_map_.erase(i);
}
}
public:
~Display()
{
boost::lock_guard<boost::mutex> g(mutex_);
for (bitmaps_t::iterator i = bitmaps_.begin(); i != bitmaps_.end(); ++i)
{
BitmapPtr ptr = i->lock();
if (ptr)
ptr->display = NULL;
}
}
BitmapPtr GetBitmap(int i)
{
BitmapPtr r(new Bitmap(i, this));
boost::lock_guard<boost::mutex> g(mutex_);
bitmaps_.push_back(boost::weak_ptr<Bitmap>(r));
bitmap_map_[r.get()] = --bitmaps_.end();
return r;
}
};
Bitmap::~Bitmap()
{
if (display)
display->Remove(this);
}
请注意,Bitmap
和Display
之间有双向链接 - 它们彼此保持弱指针,这意味着它们可以自由通信。例如,如果希望 Display 能够"销毁"位图,则只需通过将"display"更新为 NULL 来禁用它们,如析构函数Display
所示。 Display
每次想要访问位图(析构函数中的示例(时都必须锁定weak_ptr<Bitmap>
,但如果这种通信不经常发生,这应该不是什么大问题。
为了线程安全,您可能需要在每次想要"禁用"位图时锁定它,即将显示成员重置为 NULL,并在每次要从位图访问"显示"时锁定它。由于这会对性能产生影响,因此您可能希望在 Bitmap 中将Display*
替换为weak_ptr<Display>
。这也消除了在显示中使用析构函数的需要。以下是更新的代码:
class Bitmap : boost::noncopyable
{
friend class Display;
Bitmap(int, const boost::shared_ptr<Display>& d) : display(d)
{}
boost::weak_ptr<Display> display;
public:
~Bitmap(); // see below for definition
};
typedef boost::shared_ptr<Bitmap> BitmapPtr;
class Display : public boost::enable_shared_from_this<Display>
, boost::noncopyable
{
//... no change here
public:
BitmapPtr GetBitmap(int i)
{
BitmapPtr r(new Bitmap(i, shared_from_this()));
boost::lock_guard<boost::mutex> g(mutex_);
bitmaps_.push_back(boost::weak_ptr<Bitmap>(r));
bitmap_map_[r.get()] = --bitmaps_.end();
return r;
}
};
Bitmap::~Bitmap()
{
boost::shared_ptr<Display> d(display);
if (d)
d->Remove(this);
}
在这种情况下,在位图中"禁用"显示指针是线程安全的,无需显式同步,如下所示:
Display::DisableBitmap(bitmaps_t::iterator i)
{
BitmapPtr ptr = i->lock();
if (ptr)
ptr->display.reset();
}
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 资源管理设计模式
- 工厂设计模式优化
- 下面抽象工厂设计模式的实现是正确的吗
- 实现通用工厂设计模式
- 设计模式的工厂替代方法:具有不同构造函数的类
- 在任何编译语言中实现以下语法(用于工厂设计模式)? 最好是 Kotlin,C++
- 共享对象工厂的设计模式
- RAII和工厂设计模式
- 如何使工厂设计模式在C 中
- 工厂设计模式问题
- 比工厂更好的设计模式
- 通过工厂设计模式向客户隐藏新内容的优势是什么
- 如何在工厂设计模式中设置派生产品类的数据成员
- 工厂设计模式中的纯虚拟功能错误
- 资源和工厂设计模式薄弱
- 抽象工厂设计模式在c++中的应用
- 这是哪种设计模式:工厂方法还是抽象工厂
- 设计模式-使用工厂方法合并不同的类(c++)
- 具有默认实现的抽象工厂设计模式