使用設計模式優化設計案例

首先看一種簡單的實現打印二叉表達式樹

                                                                                        

簡單的實現: 使用switch 語句,分類實現

void print_tree(Tree_Node *root){
 switch(root > tag_){
case NUM: printf("%d", toot->num_);
                     break;
case UNARY:
                   printf("%s",root->op_[0]);
                   print_tree(root->unary_);
                   printf(")");
                   break;
case BINARY:
                   print_tree(root_binary_l);
                   print_tree(root_binary_r);
                   break;
default:
                   printf("error, unknown type");
}
}

typedef struct Tree_Node Tree_Node;
struct Tree_Node{
                 enum{NUM, UNARY,BINARY} tag_;
                 short use_; /*reference count*/
                 union{
                  char op_[2];
                  int num_;
}o;

#define num_  o.num_
#define op_  o.op_
union{
  Tree_Node *unary_;
  struct {Tree_Node *l_, *r_;} binary_;
}c;

#define unary_  c.unary_;
#define binary_  c.binary_
};


這種設計的缺點:

幾乎沒有使用封裝;

節點和邊的耦合性比較高;

算法的複雜性比數據結構的複雜度要高很多,算法處理的絕大部分的工作;

由於沒有封裝,可擴展性必然較差;

採用面向對象的方法:

識別的類:

class Node:

class Int_Node:

class Unary_Node:

class Binary_Node:

class Tree:

C++ Node Interface: 定義print 打印 純虛函數

class Tree; 


class Node
{
   friend class Tree;
protected:
     Node():use (1){}
     //pure
     virtual void print(std::ostream&) const =0;
public:
     int use; //reference counter.
};

C++ Tree Interface:  這裏定義了一個 符號重載函數,用於樹的打印

class  Tree
{
public:
  Tree(int);
  Tree(const string&, const Tree &);
  Tree(const string&, const Tree &,const Tree &);
  Tree(const Tree&t);
  void operator=(const Tree &t);
  ~Tree();
   void print(std::ostream&) const;
private:
  Node *node; // pointer to a rooted subtree
};

std::ostream &operator<<(std::ostream &s, const Tree& tree);

C++ Int_Node Implementation

Int_Node::Int_Node(int k):num(k){}


void Int_Node::print(std::ostream &stream)const{
     stream<<this->num;
  }

用工廠模式改進:集中初始化,方便應對變化

1. 有不同的子類型,需要集中初始化

2. 使得改變添加新的Node 變的簡單


使用工廠模式,構建Tree 的子模型

Tree::Tree(int num)
: node_ (new Int_Node (num)) {}

Tree::Tree(const string&op, const Tree &t)
  :node_(new Unary_Node(op,t)) {}

Tree::Tree(const string &op,
           const Tree &t1,
           const Tree &t2)
: node_ (new Binary_Node(op,t1,t2)){}

打印子樹(Printing Subtrees)

在打印子樹的時候,我們並不需要關心樹中節點的類型,以及他們的繼承關係。使用橋接器模式可以很好的做到這點

橋接器模式: 

提供統一的即封閉又開放的接口: 接口不允許被修改,接口允許擴展         


                                                             

void Tree::print(std::ostream &os) const{
 this->node->print(os);
}


適配器: 把類的接口轉換爲另外的接口

                                                        

適配器模式關心解決的問題:

1. 適配器模式允許不同類不因爲接口不兼容而不可共同工作。

Using Adapter Pattern

std::ostrream &operator<<(std::ostream &s, const Tree &tree)
{
    tree.print(s);// 得益於上面的橋接器模式實現
  //this triggers Node *virtual all via tree.noe->print(s), which is implemented as the following:
  //(*tree.node_->vptr[1])(tree.node_,s);
    return s;
}

C++ Main Program

#include<istd::ostream.h>
#include "Tree.h"
int main(int, char*[]){
  const Tree t1 = Tree("*", Tree("-",5),Tree("+",3,4));
  cout<<t1<<endl;  // prints ((-5) * (3 + 4))
  const Tree t2 = Tree("*",t1,t1);
 //prints (((-5)*(3+4))*((-5)*(3+4)))
 cout<<t2<<endl;
  return 0;
  // destructors of t1 ,t2 recursively
}// delete entire tree when leaving soope


使用面向對象方法也有一些潛在的問題:

解決方案通常 數據結構 部分很臃腫, 需要包含各種cpp 文件 .h 文件

可能不如最原始的方案來的效率高, 因爲包含有虛擬函數,增加了開銷


關鍵code源碼賞析: Tree.cpp

#include"Tree.h"
#include"Int_Node.h"
#include"Binary_Node.h"
#include"Unary_Node.h"

Tree::Tree(int num)
	:node(new Int_Node(num)){}

Tree::Tree(const string &op,const Tree &t)
	:node(new Unary_Node(op,t)){}

Tree::Tree(const string &op,
		   const Tree &t1,
		   const Tree &t2)
		   :node(new Binary_Node(op,t1,t2)){}

Tree::~Tree(){
	--this->node->use;
	if(this->node->use <= 0)
	{
		delete this->node;
	}
}

void Tree::print(std::ostream&os) const
{
	this->node->print(os);
}

Tree::Tree(const Tree&t):node(t.node){
 ++this->node->use;  //shareing,ref-counting;
}
void Tree::operator=(const Tree &t)
{
   if(this == &t) return;
   ++t.node->use;
   --this->node->use;
   if(this->node->use == 0)
	   delete this->node;
   this->node = t.node;
}

std::ostream &operator<<(std::ostream &s, const Tree& tree)
{
	tree.print(s);
	//This triggers Node *virtural call via
	// tree.node -> print(s), which is implemented as the following
	//(*tree.mode->vptr[1]) (tree.node, s);
	return s;
}


Project download: Here





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章