您的位置:首页 > 职场人生

黑马程序员_理解编程中抽象的概念和分层的思想

2013-03-28 19:55 239 查看
------- Windows Phone 7手机开发.Net培训、期待与您交流! -------

这篇文章主要介绍的编程思想称为抽象,认真看一下,我觉得对你的编程很有好处。今天恶补了一下C语言,学到结构体时觉得书上的例子很不错,拓展了一下,理解抽象的精髓。这些思想在.net上也完全是通用的。

先看部分代码:

//复数的结构体
struct complex_struct
{
double x; //实部
double y; //虚部
};

/*
*     复数存储表示层
*/
double real_part( struct complex_struct z )   //取复数实部
{
return z.x;
}

double img_part( struct complex_struct z )   //取复数虚部
{
return z.y;
}

double magnitude( struct complex_struct z ) //求复数的模
{
return sqrt( z.x * z.x + z.y * z.y );
}

double angle( struct complex_struct z )        //求复数的幅角
{
double PI = acos( -1.0 );
if( z.x > 0 )
return atan( z.y / z.x );
else
return atan( z.y / z.x ) + PI;
}
//直角坐标构造复数
struct complex_struct make_from_real_img( double x, double y )
{
struct complex_struct z;
z.x = x;
z.y = y;
return z;
}
//极坐标构造复数,做乘除法比较方便
struct complex_struct make_from_mag_ang( double r, double A )
{
struct complex_struct z;
z.x = r * cos(A);
z.y = r * sin(A);
return z;
}

//在此基础上就可以实现复数的加减乘除运算了:
/*
*     复数运算层
*/

//加法
struct complex_struct add_complex( struct complex_struct z1, struct complex_struct z2 )
{
return make_from_real_img( real_part(z1) + real_part(z2),
img_part(z1) + img_part(z2) );
}

//减法
struct complex_struct sub_complex( struct complex_struct z1, struct complex_struct z2 )
{
return make_from_real_img( real_part(z1) - real_part(z2),
img_part(z1) - img_part(z2) );
}

//乘法
struct complex_struct mul_complex( struct complex_struct z1, struct complex_struct z2 )
{
return make_from_mag_ang( magnitude(z1) * magnitude(z2),
angle(z1) + angle(z2) );
}

//除法
struct complex_struct div_complex( struct complex_struct z1, struct complex_struct z2 )
{
return make_from_mag_ang( magnitude(z1) / magnitude(z2),
angle(z1) - angle(z2) );

}


通过上面的代码可以看出,复数的加减乘除并没有直接访问结构体的成员x和y,而是把整个复数的结构体看成一个整体,通过相关的函数调用来实现需要的功能。这样有什么好处呢?好处多得很呢。

假如现在项目需要复数使用别的数据结构存储,例如改成用极坐标来存储,因为收集的数据不一定都是用直角坐标,假如收集的是极坐标的数据呢,用上面的函数转换总会损失一些精度,不好。

极坐标存储层的代码:

struct complex_struct
{
double r, A;
};

double real_part(struct complex_struct z)
{
return z.r * cos(z.A);
}

double img_part(struct complex_struct z)
{
return z.r * sin(z.A);
}

double magnitude(struct complex_struct z)
{
return z.r;
}

double angle(struct complex_struct z)
{
return z.A;
}

struct complex_struct make_from_real_img(double x, double y)
{
struct complex_struct z;
double PI = acos(-1.0);
z.r = sqrt(x * x + y * y);
if (x > 0)
z.A = atan(y / x);
else
z.A = atan(y / x) + PI;

return z;
}

struct complex_struct make_from_mag_ang(double r, double A)
{
struct complex_struct z;
z.r = r;
z.A = A;
return z;
}


虽然结构体的存储发生了改变,但是我们的几个复数运算需要改吗,答案是不需要,一点都不需要,仍可以使用,原因上面已经说了,复数的加减乘除并没有直接访问结构体的成员,而是把整个复数的结构体看成一个整体,就好像我们使用int一样,难道系统有天升级了,改成使用4个字节存储了,我们就要修改我们的代码了吗?所以我们要像系统那样去编程,就不难理解为什么我们看见的例子怎么那么麻烦,写那么多个函数,直接使用不就行了吗。

这里介绍的编程思想成为抽象。其实“抽象”这个概念也没那么抽象,要在编程了使用抽象,学会怎么使用抽象也不难,简单的说就是提取公因式:ab+ac=a(b+c)。如果a变了,ab和ac都要改,但如果写成a(b+c)的形式就只需要改其中一个因子了,其他都不用变。再浅显的说就是当b,c都要用到a时,把a单独提取出来,这样再明白不过了吧。

在我们的复数运算程序中,复数是有可能使用直角坐标或极坐标表示的,我们把这个有可能变动的因子提取出来组成复数的存储表示层。这一层看到的是数据结构两个成员x和y,或者r和A,如果改变了结构体的实现就要改变这一层的现象,但是我们在复数的运算层是不需要改变的,函数的接口没有改变。复数运算层看到的知识一个抽象的“复数”的概念,知道它有直角坐标和极坐标,可以调用相关的函数使用这些坐标。在往上看其他使用复数运算的程序看到的数据就更抽象了,只知道它是一个复数,和int,double型等没有什么区别,关于它里面是怎么实现的根本不需要知道。

这里的复数存储表示层和复数运算层都称为抽象层,从底层往上看,复数的概念越来越抽象了,把所有的这些层组合在一起就是一个完整的系统。组合使得系统可以任意复杂,但这种复杂性是可以控制的,不会出现牵一发而动全身,任何改动都局限在某一层。

这种思想用在.net上的开发也是通用的,比如对数据库的操作,机会每个模块都需要与数据库打交道,那么把数据库抽象出来是必须的,以后如果换了一个数据库,连接字符串不同了,SQL语句的关键字有些不同了,不抽象出来系统就有太多需要修改了,而抽象出来了只需要修改数据库这层,别的代码几乎不需要修改。然后再细分,对数据库的操作根据不同的系统有不同的业务逻辑,不同的系统数据库的表结构是不一样的,那代码怎么办,为了达到尽可的重用性,也需要抽象出来,然后界面的各种逻辑才不用去考虑不同的表结构。

认真看完这篇我整理的笔记我相信对关于编程中的抽象性一定会有个大概的了解,对个人编程也是有相当大的好处的。好的东西总想和大家一起分享,希望你也有收获。

有误请帮我指出,谢谢!共同提高。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: