一段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 |