C++ 正确的设计模式来处理对象的多态集合
假设我有以下几个类:C++ 正确的设计模式来处理对象的多态集合,c++,polymorphism,C++,Polymorphism,假设我有以下几个类: class BaseObject { public: virtual int getSomeCommonProperty(); }; class Object1: public BaseObject { public: virtual int getSomeCommonProperty(); // optional int getSomeSpecificProperty(); }; class BaseC
class BaseObject {
public:
virtual int getSomeCommonProperty();
};
class Object1: public BaseObject {
public:
virtual int getSomeCommonProperty(); // optional
int getSomeSpecificProperty();
};
class BaseCollection {
public:
virtual void someCommonTask();
};
class Collection1: public BaseCollection {
public:
virtual void someCommonTask(); // optional
void someSpecificTask();
};
从BaseCollection派生的每个集合都处理特定的对象类型(并且只有一种类型)。但是BaseCollection应该能够执行一些对所有对象通用的任务,只使用BaseObject中的通用对象属性
目前,我考虑的可能有三种解决方案:
1) 将对象列表存储在BaseCollection中,例如:
class BaseCollection {
vector<BaseObject*> objects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
}
类基集合{
矢量对象;
};
这个解决方案的问题是,当我需要在Collection1中执行特定于对象的任务时,我需要一个动态的\u转换,因为我不想对特定的属性使用虚拟固有,只应用于一种类型的对象。考虑到dynamic_cast可能每秒被调用数百万次,这似乎是性能关键型应用程序的一个问题 2) 将对象列表存储在Collection1中,例如:
class BaseCollection {
vector<BaseObject*> objects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
}
class Collection1:公共BaseCollection{
矢量对象;
}
但是我需要一些方法来访问BaseCollection中的这个对象列表,以便能够对它们执行一些常见的任务,最好是通过迭代器。我需要创建一个函数,为BaseCollection返回一个向量,但这似乎不是很有效,因为唯一的方法是创建一个新向量(可能包含数千个对象)
3) 将对象列表存储在BaseCollection和Collection1中:
class BaseCollection {
public:
void someCommonTask(); // Use baseObjects
virtual void addObject() = 0;
protected:
vector<BaseObject*> baseObjects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
}
类基集合{
公众:
void someCommonTask();//使用baseObjects
虚拟void addObject()=0;
受保护的:
矢量基对象;
};
类集合1:公共BaseCollection{
矢量对象;
公众:
虚拟void addObject(){
Object1*obj=newobject1;
物体。推回(obj);
基本对象。推回(obj);
}
void someSpecificTask();//使用对象,无需动态强制转换
}
这两个列表实际上包含相同的对象。这是不是听起来那么难看
我正在为这类问题寻找正确/正确/最佳的设计模式,上面提到的3种解决方案都不能让我满意
也许可以用模板解决这个问题,但我看不到一种存储多态集合列表的方法,如下所示:
vector<BaseCollection*> collections;
向量集合;
我认为您应该选择选项1,但应使用静态强制转换。毕竟派生集合确实知道成员变量的类型
解释得很好。我认为解决方案应该是和的混合。看一看这些,以完善您的设计 编辑:下面是一个示例代码
GenericProduct
是BaseObject
,它提供了两个方法,一个是通用的(尽管可以重写),另一个是不做任何事情的特定方法,它不是纯虚拟的,因此可以实例化这个类SpecificProduct
是一个子类,它以某种方式实现了特定的方法
现在,Factory
类是一个抽象类,它定义了一个由特定工厂创建特定产品的接口,它定义了一个创建产品的纯虚拟方法createProduct
。创建了两个具体的工厂GenericFactory
和SpecificFactory
,它们创建特定的产品
最后,Consumer
抽象类(对应于代码中的BaseCollection
),它定义了一个纯虚拟方法来创建工厂createFactory
,以强制子类创建自己的具体工厂(从而创建正确的产品)。该类还定义了一个方法fillArray
(原型模式),用工厂创建的产品填充数组
#include <iostream>
#include <vector>
using namespace std;
class GenericProduct{
public:
virtual void getSomeCommonProperty()
{
cout<<"Common Property\n";
}
virtual void getSomeSpecificProperty()
{
cout<<"Generic Has Nothing Specific\n";
}
};
class SpecificProduct : public GenericProduct{
public:
virtual void getSomeSpecificProperty()
{
cout<<"Specific Product Has a Specific Property\n";
}
};
class Factory
{
public:
virtual GenericProduct* createProduct() = 0;
};
class GenericFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new GenericProduct();
}
};
class SpecificFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new SpecificProduct();
}
};
class Consumer
{
protected:
vector<GenericProduct*> gp;
Factory* factory;
protected:
virtual void createFactory() = 0;
public:
void fillArray()
{
createFactory();
for(int i=0; i<10; i++)
{
gp.push_back(factory->createProduct());
}
}
virtual void someCommonTask()
{
cout<<"Performaing a Common Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeCommonProperty();
}
}
virtual void someSpecificTask()
{
cout<<"Performaing a Specific Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeSpecificProperty();
}
}
};
class GenericConsumer : public Consumer
{
virtual void createFactory()
{
factory = new GenericFactory();
}
};
class SpecificConsumer : public Consumer
{
virtual void createFactory()
{
factory = new SpecificFactory();
}
};
int main()
{
Consumer* c = new GenericConsumer();
c->fillArray();
c->someCommonTask();
return 0;
}
#包括
#包括
使用名称空间std;
类泛型产品{
公众:
虚拟void getSomeCommonProperty()
{
难道这就够了吗
class CollectionManipulator {
public:
void someCommonTask(BaseCollection& coll) {
for(unsigned int i = 0; i < coll.size(); i++)
someCommonTask(coll.getObj(i));
}
private:
void someCommonTask(BaseObject*); // Use baseObjects
};
class BaseCollection {
friend class CollectionManipulator;
private:
virtual BaseObject* getObj(unsigned int) = 0;
virtual unsigned int size() const = 0;
};
class Collection1 : public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
private:
BaseObject* getObj(unsigned int value) {
return object[value];
}
unsigned int size() const {
return objects.size();
}
}
类集合操纵器{
公众:
void someCommonTask(BaseCollection和coll){
for(无符号整数i=0;i
如果您想在Collection1中抽象您的容器(比如使用list而不是vector),要在操纵器中使用它,请创建一个抽象迭代器…Id使用嵌套适配器,如下面的示例所示。您必须为每个要进行奇特更新的类专门化它
!该示例存在内存泄漏-分配的A、B、Q对象不会被删除
#include <iostream>
#include <vector>
#include <algorithm>
class Q
{
public:
virtual void Foo()
{
std::cout << "Q::Foo()" << std::endl;
}
};
class A
{
public:
virtual void Foo()
{
std::cout << "A::Foo()" << std::endl;
}
};
class B : public A
{
public:
virtual void Foo()
{
std::cout << "B::Foo()" << std::endl;
}
virtual void BFoo()
{
std::cout << "B::BFoo()" << std::endl;
}
};
template <typename ElementType>
class C
{
public:
template <typename T>
void add(T* ptr){m_Collection.push_back(std::unique_ptr<Adapter>(new ConcreteAdapter<T>(ptr)));}
void updateAll()
{
std::for_each(m_Collection.begin(), m_Collection.end(), [&](std::unique_ptr<Adapter> &adapter)->void{adapter->update();});
}
private:
class Adapter
{
public:
virtual ElementType* get() = 0;
virtual void update(){get()->Foo();}
};
template <typename T>
class ConcreteAdapter : public Adapter
{
public:
ConcreteAdapter(T* ptr) : m_Ptr(ptr){}
virtual T* get(){return m_Ptr;}
protected:
T* m_Ptr;
};
template <>
class ConcreteAdapter<B> : public Adapter
{
public:
ConcreteAdapter(B* ptr) : m_Ptr(ptr){}
virtual B* get(){return m_Ptr;}
virtual void update()
{
get()->Foo();
get()->BFoo();
}
private:
B* m_Ptr;
};
std::vector<std::unique_ptr<Adapter>> m_Collection;
};
int main()
{
C<A> c;
c.add(new A());
c.add(new B());
//c.add(new Q()); //error - correct
c.updateAll();
return 0;
}
#包括
#包括
#包括
Q类
{
公众:
虚拟void Foo()
{
std::cout您可以通过基类(智能)指针将基类和派生类的所有对象存储在一个集合中。使用and机制,您可以仅对特定类型的对象调用函数,而无需在基类接口中公开该函数。例如:
#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <stdio.h>
struct Visitor { // Visitor design patter
virtual void visit(struct BaseObject&) {}
virtual void visit(struct Object1&) {}
};
struct BaseObject {
unsigned ref_count_; // intrusive_ptr support
BaseObject() : ref_count_() {}
virtual ~BaseObject() {}
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
void intrusive_ptr_add_ref(BaseObject* p) { // intrusive_ptr support
++p->ref_count_;
}
void intrusive_ptr_release(BaseObject* p) { // intrusive_ptr support
if(!--p->ref_count_)
delete p;
}
struct Object1 : BaseObject {
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
void getSomeSpecificProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class T, class Functor>
struct FunctorVisitor : Visitor {
Functor f_;
FunctorVisitor(Functor f) : f_(f) {}
void visit(T& t) { f_(t); } // apply to T objects only
template<class P> void operator()(P const& p) { p->accept(*this); }
};
template<class T, class Functor>
FunctorVisitor<T, Functor> apply_to(Functor f)
{
return FunctorVisitor<T, Functor>(f);
}
int main()
{
typedef boost::intrusive_ptr<BaseObject> BaseObjectPtr;
typedef std::vector<BaseObjectPtr> Objects;
Objects objects;
objects.push_back(BaseObjectPtr(new BaseObject));
objects.push_back(BaseObjectPtr(new Object1));
for_each(
objects.begin()
, objects.end()
, boost::bind(&BaseObject::getSomeCommonProperty, _1)
);
for_each(
objects.begin()
, objects.end()
, apply_to<BaseObject>(boost::bind(&BaseObject::getSomeCommonProperty, _1))
);
for_each(
objects.begin()
, objects.end()
, apply_to<Object1>(boost::bind(&Object1::getSomeSpecificProperty, _1))
);
}
“因为我不想对特定属性使用虚拟内在性”这意味着每次我用特定属性创建一个新类型的对象(只能由其相应的集合使用),我都必须在BaseObject中添加一个虚拟函数,它是compl