关于设计模式的问题

grymx1981 2008-07-12 05:14:22
在我的程序中有很多种类的模型,如cat,dog,fish,bird等等
每个模型又会有很多实例(instance),这些模型有很多相同的行为如eat()
但也有一些特有的属性,如cat和dog都会run()
如果我希望所有的模型都eat()的话,那我需要对每种模型都用一个for或while循环遍历
如果模型很多且eat这种行为也很多的话,会使我的程序代码变得很长
能不能通过一个循环,遍历所有的模型,调用所有模型的成员函数eat()
一种方法是实现一个公共的基类animal,之后所有的模型都从这个基类派生
cat:public animal;
dog:public animal;
……
这能解决大部分问题,但是,当我需要调用所有会run模型的时候,我还是需要通过2个循环
分别遍历cat和dog,如果还是通过再建立一个基类runAnimal来派生cat和dog的话,会不会使
程序的继承结构过于复杂从而降低性能,另外,当cat和fish有着共同的行为fly的时候又怎么办
我希望能通过一种统一的方式调用这些成员函数而不是对每种模型进行循环,请问这是不是可以实现
用什么样的设计模式可以实现,谢谢
...全文
596 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
liruda 2010-03-30
  • 打赏
  • 举报
回复
可以用Composite 来组合所有对象, 使它们具有一致性而不必区别对待.
用Iterater模式来遍历对象s.
autoopen 2010-03-05
  • 打赏
  • 举报
回复
路过,真的路过,路过,真的路过
testing2007 2010-03-05
  • 打赏
  • 举报
回复
to yifanernei, 写的不错,如果没有判断错误的话,这个应该可以称为command的设计模式。
zhaoyongcai123 2009-12-15
  • 打赏
  • 举报
回复
不错不错
huangyd33 2009-09-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yifanernei 的回复:]
C/C++ codeclass IRun
{public:virtualvoid run()=0;
};class DogRun :public IRun
{public :void run() { cout<<"dog run"<<endl; }
};class CatRun :public IRun
{public :void run() { cout<<"cat run"<<endl; }¡­
[/Quote]

非常赞同你的解法,但是提个小建议。在遍历容器的时候,尽量用iterator不要用size的这种形式,不太安全。
另外你用的应该是策略模式吧。
uglylourt 2009-09-04
  • 打赏
  • 举报
回复
其实你用了多态,再多加一层继承效率也是一样了。

如果你不用虚函数来继承,不用棱形继承。使用继承再多也不会影响效率的。

这个可以看看《C++对象模型》。
coxfilur_2008 2009-06-29
  • 打赏
  • 举报
回复
up
seysey 2009-05-27
  • 打赏
  • 举报
回复
mark
大写的池 2008-09-06
  • 打赏
  • 举报
回复
使用一个基类,再使用一些中间类
Jinhao 2008-09-06
  • 打赏
  • 举报
回复
std::cout<<"Now, flyable begin to flying"<<std::endl;

写成 eating了.
Jinhao 2008-09-06
  • 打赏
  • 举报
回复

template<typename T>
struct world{};

class abstract_animal
{
public:
virtual ~abstract_animal(){}
virtual void eat() = 0;
};
//----------------------------------------------
template<>
class world<abstract_animal>
{
public:
typedef abstract_animal concept_type;

void insert(abstract_animal* aa)
{
objects_.push_back(aa);
}

void erase(abstract_animal* aa)
{
objects_.erase(std::find(objects_.begin(), objects_.end(), aa));
}

void eat() const
{
std::for_each(objects_.begin(), objects_.end(), *this);
}

void operator()(concept_type* eatable) const
{
eatable->eat();
}
private:
static std::vector<concept_type*> objects_;
};

template<> std::vector<abstract_animal*> world<abstract_animal>::objects_;

class animal
:public abstract_animal
{
public:
typedef abstract_animal concept_type;

animal()
{
world<concept_type> w;
w.insert(this);
}

~animal()
{
world<concept_type> w;
w.erase(this);
}
};
//--------------------------
class abstract_flyable: public abstract_animal
{
public:
virtual void fly() =0;
};

template<>
class world<abstract_flyable>: public world<abstract_animal>
{
public:
typedef world<abstract_animal> base_type;
typedef abstract_flyable concept_type;

void insert(concept_type* aa)
{
base_type::insert(aa);
objects_.push_back(aa);
}

void erase(abstract_animal* aa)
{
objects_.erase(std::find(objects_.begin(), objects_.end(), aa));
base_type::erase(aa);
}

void fly() const
{
std::for_each(objects_.begin(), objects_.end(), *this);
}

void operator()(concept_type* object) const
{
object->fly();
}
private:
static std::vector<concept_type*> objects_;
};

template<> std::vector<abstract_flyable*> world<abstract_flyable>::objects_;

class flyable: public abstract_flyable
{
public:
typedef abstract_flyable concept_type;

flyable()
{
world<concept_type> w;
w.insert(this);
}

~flyable()
{
world<concept_type> w;
w.erase(this);
}
};
//-------------------------
class cat: public animal
{
public:
void eat()
{
std::cout<<"Cat("<<this<<") is eating very happy"<<std::endl;
}
};

class dog: public animal
{
public:
void eat()
{
std::cout<<"Dog("<<this<<") is eating very happy"<<std::endl;
}
};

class bird: public flyable
{
public:
void eat()
{
std::cout<<"Bird("<<this<<") is eating worms"<<std::endl;
}

void fly()
{
std::cout<<"Bird("<<this<<") is flying so happy"<<std::endl;
}
};


int main()
{
cat c1;
cat c2;

dog d;
bird b1;
bird b2;


std::cout<<"Now, eatable begin to eating"<<std::endl;
world<abstract_animal> w_animal;
w_animal.eat();

std::cout<<"Now, flyable begin to eating"<<std::endl;
world<abstract_flyable> w_flyable;
w_flyable.fly();
}

overbai 2008-09-06
  • 打赏
  • 举报
回复
建立一个公共虚基类,运用继承,然后就如7楼那样!
因为容器vector支持对异类的操作。
laiwusheng 2008-09-06
  • 打赏
  • 举报
回复
定义可扩展的工厂 Abstract Factory,通常为每一种模型定义一个操作。模型的种类被编码在操作型构中。增加一种新的模型要求改变Abstract Factory的接口以及所有与它相关的类。一个更灵活但不太安全的设计是给创建对象的操作增加一个参数。该参数指定了将被创建的对象的种类。它可以是一个类标识符、一个整数、一个字符串,或其他任何可以标识这种模型的东西。实际上使用这种方法,Abstract Factory只需要一个“action”操作和一个指示要创建对象的种类的参数。
ViCross 2008-09-04
  • 打赏
  • 举报
回复
面向方面, 面向功能是解决的方法;
**able(), 都可以作为功能封装起来, 然后调用Get**able()就可以了
qhfu 2008-07-18
  • 打赏
  • 举报
回复
从你的描述来看,我觉得 有两种方案,
1, 提供一个 animal 基类, runnable , flyable 两个接口, c++中用抽象类。。多继承, 不算太好。。

2, 还有就是: 把动物的行为委托给另外一个类。
jieao111 2008-07-17
  • 打赏
  • 举报
回复
mark
taodm 2008-07-17
  • 打赏
  • 举报
回复
显然,你面对的是类的数目极不稳定,要支持的同名方法的数目也不稳定。
C++显然不是对付这种场合的好选择,没啥好的方案,总是顾了这头就露出那头。
换python等动态语言比较合理。
yifanernei 2008-07-17
  • 打赏
  • 举报
回复
假如多个种类的eat形为相同,可实现iEat的eat函数,使之具有默认操作,而不是一个纯虚函数
yifanernei 2008-07-17
  • 打赏
  • 举报
回复

class IRun
{
public:
virtual void run() = 0;
};

class DogRun : public IRun
{
public :
void run() { cout <<"dog run" <<endl; }
};

class CatRun : public IRun
{
public :
void run() { cout <<"cat run" <<endl; }
};

class IEat
{
public:
virtual eat() = 0;
};

class DogEat : public IEat
{
public :
void eat() { cout <<"dog Eat" <<endl; }
};

class CatEat : public IEat
{
public :
void eat() { cout <<"cat Eat" <<endl; }
};

class FishEat : public iEat
{
public :
void eat() { cout <<"fish Eat" <<endl; }
};

class Animal
{
public :
Animal() { m_pRun = m_pEat = NULL; }
~Animal() { delete m_pRun, m_pEat; }

void Run() { if (m_pRun) m_pRun->run(); }
void Eat() { if (m_pEat) m_pEat->eat(); }
protected :
IRun * m_pRun;
IEat * m_pEat;
};

class Dog : public Animal
{
public:
Dog() { m_pRun = new DogRun; m_pEat = new DogEat;}
};

class Cat : public Animal
{
public:
Cat() { m_pRun = new CatRun; m_pEat = new CatEat;}
};

class Fish : public Animal
{
public;
Fish() { m_pEat = new FishEat; }
};


int main()
{
vector<Animal *> vctAnimals;

vctAnimals.push_back(new Dog());
vctAnimals.push_back(new Cat());
vctAnimals.push_back(new Fish());

for (int i=0; i<vctAnimals.size(); ++i)
{
vctAnimals[i].Run();
vctAnimals[i].Eat();
}


for (int i=0; i<vctAnimals.size(); ++i)
{
delete vctAnimals[i];
}

return 0;
}
bitxinhai 2008-07-16
  • 打赏
  • 举报
回复
可以考虑使用工厂模型!!!
加载更多回复(5)

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧