您的位置:首页 > 其它

使用设计模式优化设计案例<一>

2016-02-23 21:27 573 查看
首先看一种简单的实现打印二叉表达式树



简单的实现: 使用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: