您的位置:首页 > 移动开发 > Objective-C

Object Oriented Design -- Data and Algorithm Separation (1)

2014-04-03 21:09 501 查看
摘要:主要介绍软件设计过程中数据和算法分离的原则,以及用一个例子(可以适用于任何数据结构的通用二叉树算法)说明了具体的实现方式。这种设计思想其实与STL标准库中采用的方法很相似,不仅适用于二叉树,也适用于其他一些算法,之所以使用二叉树是人人都能理解的一种数据结构,而且算法简单。文档主体是用英文写的,可能不太通顺,请见谅。

One of STL library's basic traits and advantages is the data and aogorithm separation, actually it is a good principle in generic OO design. With data and algorithm seperation in your design, if there's any change in either data or algorithm part, the other
part will not get influenced. Below I will design a basic binary tree class that applies this principle, using this as an example.

The purpose of this project is to design a basic binary class that could handle virtually any data types, first let's recall the classic binary tree implementation in the text book, it is something like this:

struct bt_node {
int _data;
struct bt_node* left;
struct bt_node* right;
};


Here you can see that this is a demonstration of data/algorithm comnbination, _data is the actuall data we need, left and right are related with binary tree algorithms, you have to combine data and algorithm related stuff together in order to apply algorithm
on data. If the data changes, like:

struct bt_node {
struct contact{
int id;
std::string name;
std::string address;
std::string phone;
data_time birthday;
char *some_other_info;
......
} _data;
struct bt_node* left;
struct bt_node* right;
};
you will need to change the algorithm accordingly.

To achieve data/algorithm separation, I could use the similar technology used in STL libraries, e.g, use template meta programming. First, we can see that the two child pointers left and right both belong to the algorithm part, and are used inside binary tree
algorithms internally only. So we could design binary tree class like this:

class BinaryTree
{
public:
struct Node
{
data_type some_data;
Node* left;
Node* right;
};

void some_other_methods();
......

private:
Node* m_root;
};


To embed data into this binary tree structure and algorithm, I need some common interface to interact with all kinds of data. I classify data into 2 kinds, key that could be sorted(like id), and actual data(like name, address, etc.), and also I need to know
the data's type. So, I come to this design:

template<class T> class BinaryTree
{
public:
typedef typename T::key_type key_type;
typedef typename T::data_type data_type;

struct Node
{
T data;
Node* left;
Node* right;

Node() : data(T()), left(nullptr), right(nullptr) {};
Node(const T& d) : data(d), left(nullptr), right(nullptr) {};
explicit Node(const key_type& k, const data_type& d) : data(k, d), left(nullptr), right(nullptr) {};

const key_type GetKey(void) const { return data.get_key(); };
const data_type GetData(void) const { return data.get_data(); };

void SetData(data_type d) { data.set_data(d); };
};

void some_other_methods();
......

private:
Node* m_root;
};


To achieve data/algorithm separation, the data should provide key_type and data_type 2 types, and also the methods to manipulate data(get_key(), get_data(), and set_data(), etc.). So the data definition should be like this:

class some_data
{
public:
typedef int key_type;
typedef std::string data_type;

const key_type get_key(void) const { return _key; };
const data_type get_data(void) const { return _data; };
void set_data(const data_type& d) { _data = d; };
some_other_methods();
......

private:
key_type _key;
data_type _data;
};
If any data type satisfies these requirements, it could be operated by the algorithm part disregarding the internal difference, and so the data and algorithm could be separated.

EXAMPLE:

In the header file below, I defined 2 different data structures to be used in the binary tree algorithm.

//
// FILE: data_def.h, defining data stuctures to be used in binary tree.
// Author: DGU, email: gdyxgzy@hotmail.com
// If you would like to use whole or part of this code or forward this article,
// please keep this header, and send an email to my inbox.
//
#ifndef DATA_DEF_HEADER
#define DATA_DEF_HEADER

#include <string>

class DataStruct1
{
public:
typedef int key_type;
typedef std::string data_type;

//DataStruct1() : _key(0), _data(std::string()) {};
DataStruct1(const key_type& k, const data_type& d) : _key(k), _data(d) {};

const key_type get_key(void) const { return _key; };
const data_type get_data(void) const { return _data; };
//void set_data(const data_type& d) { _data = d; };

//I used std::find in build_tree, so I need this == operator
bool operator == (const DataStruct1& a) const { return _key==a._key; };

private:
key_type _key;
data_type _data;
};

class DataStruct2
{
public:
typedef double key_type;
typedef double data_type;

//DataStruct2() : dbl(0.0) {};
DataStruct2(double d) : dbl(d) {};

const key_type get_key(void) const { return dbl; };
const data_type get_data(void) const { return dbl; };
//void set_data(double d) { dbl = d; };

bool operator == (const DataStruct2& a) const { return dbl==a.dbl; };

private:
double dbl;
};

//
// Well, you could define some other data structures here
//
#endif

// -------------- END OF THIS FILE --------------------//


Notes:

1. To use the algorithm, the data structure should at least have a default constructor, in these 2 test cases, because they are relatively simple, you even do not have to provide one. Also, to make object construction simpler, I provided a constructor with
arguments each.

2. Another thing to be noted is the == operator. Actually it is not mandotary, it is only because that I used std::find() method in constructing the binary tree object, so I will need this operator.

3. Also, I require that the key must be unique in order to construct the trees(please see the comments in build_tree() in the following article), this requirement is not mandatory in real applications.

Above is the data definition part of this code, the binary tree and algorithm related code will be posted in the following article.

(To be continued ......)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: