我正在尝试实现Flyweight模式,但我不确定继承如何工作,因此我不确定这种模式如何工作。
比方说,我有一个超类,其中包含所有“大量”信息-纹理等内在信息(永不改变的信息)。
class Block{
public: //for the sake of the example
Texture tex;
etc.
};
我的轻量级课程的数据会发生变化:
class Block_light : public Block {
public:
int posX, posY, posZ;
int color;
etc.
};
因此,如果我主要创建n Block_light
,我是否还将创建n Block
还是将它们全部绑定到一个实例?
int main(){
std::vector<Block_light> blocks(n);
return 0;
};
我创建了n Block_light
和1 Block
还是n Block_light
和n Block
?如果是后者,我该如何做,使其仅使用一个实例?
答案 0 :(得分:1)
您实现的不是轻量级模式。没有Block_light
这样的东西,而是Block
会是Block1
之类提供的实现的纯接口,该实现类似于您的Block
定义。
例如:
#include <string>
#include <unordered_map>
#include <memory>
class BlockState {
public:
int posX, posY, posZ;
int color;
};
struct Texture {
Texture(const std::string &);
char data[8196];
};
class Block {
public:
Block(std::string) {};
virtual void render(const BlockState &state) const = 0;
};
class Block1 final : public Block {
public:
Block1(std::string name) : Block(name), tex(name) {};
void render(const BlockState &state) const override;
private:
const Texture tex;
};
class BlockFactory final {
public:
std::shared_ptr<const Block> getBlock(const std::string &key) {
auto it = dict.find(key);
if(it != dict.end()) return it->second;
auto it2 = dict.try_emplace(key, std::make_shared<Block1>(key));
return it2.first->second;
}
private:
std::unordered_map<std::string, std::shared_ptr<const Block>> dict;
};
void render () {
static BlockFactory factory;
BlockState a, b;
factory.getBlock("brick")->render(a);
factory.getBlock("brick")->render(b);
}
BlockFactory
正在为您管理Block
的实例,由不可见的Block1
实现来实现。使用其他工厂进行测试等,您可以根据需要切换下面的实现以进行测试。
您的“每个实例”状态不是从Block
继承,而是保持独立和按值保留,因为Block
实例由BlockFactory
拥有,并且仅通过引用传递/指针。
答案 1 :(得分:1)
C ++对象模型可确保子类(即派生的类)的每个实例contains以及其所有超类(即 base 类)的自己的实例)。
在您的情况下,这意味着每个Block_light
对象将具有所有Block_light
属性,以及具有所有Block
属性的Block
子对象。换句话说,Block_light
一点也不轻。
如果您要共享一个公共状态:
Block_light
不会继承自Block
,而是引用共享的Block
对象。Block
和Block_light
,则可以使两者都从一个公共接口(即仅具有虚函数且没有状态的clss)继承{{1} }。 第一个选项如下:
IBlock
第二个选项是:
class Block {...};
class Block_light { // no inheritance
shared_ptr<Block> b; // but (private) composition
...
};
最后一个将这样使用:
class IBlock { // no member variables
public:
virtual Texture get_texture()=0;
virtual ~IBlock(){};
};
class Block : public IBlock { // sharable state
Texture tex;
public:
Texture get_texture() override { return tex; }
};
class Block_light : public IBlock {
shared_ptr<IBlock> b; // or IBlock or Block depending on the needs.
public:
Block_light (shared_ptr<IBlock>i) : b(i) {}
Texture get_texture() override { return b->get_texture(); }
};
int main() { // just a perfectible quick example
auto myb=make_shared<Block>();
Block_light b1(myb);
b1.get_texture();
}
我将不介绍flyweight实现的详细信息,但是您有an example here。但是,在选择此模式之前请三思,因为提供共享上下文可能具有挑战性并且容易出错。