一段c++builder下的老代码。 用组合模式来实现组织结构,singleton的OrgTreeRepository来保存所有对象。 稍有问题的地方就是一部分构造界面的代码渗入到了实体对象中--MakeChildTreeView(),这个因为用它来初始化界面中的人员组织树简直是太干净了,实在没法抵挡这种诱惑。其它的业务方法差不多是相同的逻辑,去掉了。
//---------------------------------------------------------------------------
#ifndef OrganizationH #define OrganizationH #include <Classes.hpp> #include <vector> #include <list> #include "Global/Global.h" #include "mylib/mylib/Object_Manager.h" #include "DataModule/PersistHome.h" #include <memory> #include "DataModule/Persist.h" #include "mylib/mylog.h" using namespace std; using namespace mylib; using namespace planmanage; //--------------------------------------------------------------------------- class Party { public: virtual void MakeChildTreeView(TTreeView * tree, TTreeNode* fnode)=0;
void SetName(const String &arg) { this->m_name=arg; }
const String GetName() { return m_name; }
virtual bool IsLeaf()=0;
virtual Party* FindByName(const String & name)=0;
virtual Party* FindById(const String & id) =0;
virtual void AddChild(Party* party)=0;
virtual String GetParentId()=0;
virtual ~Party(){}
virtual void Dump()=0;
virtual void DumpChild()=0;
void SetParent(Party* arg) { m_parent = arg; }
Party* GetParent() { return m_parent; }
int GetLevel() { int ret=0; Party * cursor = this->GetParent(); while(cursor) { cursor = cursor->GetParent(); ret++; } return ret; }
protected: TTreeNode* AddTreeViewNode(TTreeView *tree, TTreeNode* fnode) { TTreeNode* node = tree->Items->AddChildObject(fnode,m_name,this); node->ImageIndex = IsLeaf() ? 1 : 0; return node; }
String m_name;
Party* m_parent;
};
class Organization : public Party, public Persist<> { public: Organization() { }
void MakeChildTreeView(TTreeView * tree, TTreeNode* fnode) { TTreeNode* node = AddTreeViewNode(tree,fnode); for(size_t i=0; i<m_children.size(); i++) { m_children[i]->MakeChildTreeView(tree, node); } }
bool IsLeaf() { return false; }
Party* FindByName(const String & name) { if(this->GetName()==name) return this; else { for(size_t i=0;i<m_children.size();i++) { Party* ret = m_children[i]->FindByName(name); if(ret) return ret; } } return NULL; }
Party* FindById(const String & id) { if(this->GetId()==id) return this; else { for(size_t i=0;i<m_children.size();i++) { Party* ret = m_children[i]->FindById(id); if(ret) return ret; } } return NULL; }
void AddChild(Party* party) { m_children.push_back(party); }
String GetParentId() { return m_pid; }
~Organization() { ClearContainer(&m_children); }
void Dump() { log()<<"Dep: "+string(m_name.c_str())<<endl; log()<<"-------------"<<endl; for(size_t i=0; i<m_children.size();i++) { m_children[i]->Dump(); } log()<<"-------------"<<endl; }
void DumpChild() { log()<<"all children"<<endl; for(size_t i=0; i<m_children.size();i++) { log()<<m_children[i]->GetName().c_str()<<endl; } }
protected: void Bind() { BindTable("DOCMAN.DEPARTMENT","ID"); BindField<StringBinding>(m_name, "MANE"); BindField<StringBinding>(m_pid,"PARENT_ID"); }
private: vector<Party *> m_children; String m_pid; };
class Employee : public Party, public Persist<false> { public: void MakeChildTreeView(TTreeView * tree, TTreeNode* fnode) { AddTreeViewNode(tree,fnode); }
bool IsLeaf() { return true; }
Party* FindByName(const String & name) { if(this->GetName()==name) return this; else return NULL; }
Party* FindById(const String & id) { if(this->GetId()==id) return this; else return NULL; }
void AddChild(Party* party) { //do nothing }
String GetParentId() { return m_depId; }
void Dump() { log()<<"Staff: "+string(m_name.c_str())<<endl; }
void DumpChild() { log()<<"leaf node"<<endl; }
protected: void Bind() { BindTable("DOCMAN.STAFFINFO", "STAFFNO"); BindField < StringBinding > (m_name, "STAFFNAME"); BindField < StringBinding > (m_depId, "DEPARTNO"); } private: String m_depId;
};
//singlton class OrgTreeRepository : public Cleanup { public: static OrgTreeRepository * GetInstance() { if(!m_instance) { m_instance = new OrgTreeRepository(); mylib::Object_Manager::at_exit(m_instance); } return m_instance; }
Party * GetTreeRoot() { return m_root; }
Party * FindByName(const String &name) { return m_root->FindByName(name); }
Party * FindById(const String &id) { return m_root->FindById(id); }
Organization * GetJY() { return dynamic_cast<Organization*>(m_root->FindById(JY_DEP_ID)); }
Organization * GetZZ() { return dynamic_cast<Organization*>(m_root->FindById(ZZ_DEP_ID)); }
Organization * GetSB() { return dynamic_cast<Organization*>(m_root->FindById(SB_DEP_ID)); }
Organization * GetHZ() { return dynamic_cast<Organization*>(m_root->FindById(HZ_DEP_ID)); }
Organization * GetRootOrg() { return dynamic_cast<Organization*>(m_root); }
private: static OrgTreeRepository * m_instance;
OrgTreeRepository() { InitOrgTree(); }
~OrgTreeRepository() { delete m_root; }
Party * m_root;
void InitRootNode() { Organization * org= new Organization(); org->SetId(0); org->SetParent(NULL); org->Load(); m_root = org; }
void InitOrgTree() { InitRootNode(); auto_ptr< list<Organization*> > orgs( PersistHome < Organization, list<Organization*> >::SelectByFilter("id <> 0") ); AddKindNodes(orgs.get()); ClearContainer(orgs.get()); auto_ptr< list<Employee*> > emps(PersistHome < Employee, list<Employee*> >::SelectAll()); AddKindNodes(emps.get()); ClearContainer(emps.get()); }
template < typename CollectionType> void AddKindNodes(CollectionType *collection) { typedef CollectionType::iterator Iterator; if(!collection) return; //循环取出,直至大小不再变化 size_t vane=0; while(!collection->empty()&& collection->size()!=vane) { vane=collection->size(); for(Iterator i=collection->begin(); i!=collection->end(); i++) { Party* parent = m_root->FindById((*i)->GetParentId()); if(parent) { parent->AddChild(*i); (*i)->SetParent(parent); i=collection->erase(i); } } } } };
#endif 
|