一、什么是封装?
顾名思义,封:封闭,装:装起来,将具体的实现细节装到一个容器中,并封闭起来,防止容器外部直接访问容器内部的实现细节,仅公开暴露指定的访问路径;生活中的例子:到饭馆吃饭,你只需要跟服务员讲你要吃什么饭菜,服务员就会跟后台厨房的厨师说明一下,等待一段时间后,饭菜就被服务员直接递送到你面前,作为客户的你是不知道也无需知道饭菜的具体做法,后台厨房的厨师及做饭菜的过程就是被封装的细节,而服务员则是公开暴露的访问路径,你只能通过服务员点餐然后获得饭菜,而不能直接去到后台厨房要求厨师如何做饭菜;
二、封装的作用是什么?
1.隔离性:
被封装后的对象(这里的对象是泛指代码的编程单元,一般指:程序集,命名空间,类,方法,属性,变量等)其外部对象是无法直接访问对象的内部实现细节,内部实现细节的的改动不会影响到外部对象的访问原则(即:对象内部修改后,在公开暴露指定的访问路径不变的情况下,外部访问它的对象是无需修改的),这是隔离性的体现,同时也是实现高内聚,低耦合的最根本的思想之一;
2.可复用性:
被封装后的对象可以被外部多个对象访问,而无需为每个外部对象去指定不同的服务对象;如:所有的对象的基类都是object类,object类里面的公共成员可以被其所有子类使用,Ado.Net相关的数据访问类及其公共成员均可被其它所有的对象使用等。
3.可读性:
被封装后的对象的名称(如:程序集名,类名,方法名)如果命名恰当,那么就能在不看里面的实现细节的前提下,了解该对象的作用;如:DataTable就是用来装表格数据的;ToString就是转换为字符串,Length就是指长度等。
三、封装的禁忌
1. 忌封装过度
如:
1
2
3
4
5
6
7
|
string
a =
"a"
;
string
b =
"b"
;
string
c =
"c"
;
string
d =
"d"
;
string
joinString = a + b + c + d;
Console.WriteLine(joinString);
|
改进后的代码:
1
2
|
string
joinString =
"{0}{1}{2}{3}"
;
joinString =
string
.Format(joinString,
"a"
,
"b"
,
"c"
,
"d"
);
|
这是典型的封装过度,太过原子化,为每一个字符串都定义一个变量,代码量增加,且效率也不高,而改进后代码精简且效率高。
当然还有一些封装过度,比如:一个方法或一个类的代码量非常多,假设有一个数学计算类,可以计算所有的数字类型和所有的数学计算方法,想象一下它的代码量会有多少,这个时候就应该考虑进行适当的拆分封装,至少可以拆成数学类型类及数学计算类。
2. 忌不恰当的封装
如:
1
2
3
4
5
6
7
8
9
|
static
bool
IsNullOrEmpty(
string
str)
{
return
string
.IsNullOrEmpty(str);
}
static
bool
IsNotNullOrEmpty(
string
str)
{
return
!
string
.IsNullOrEmpty(str);
}
|
从上述代码可以看出,String的IsNullOrEmpty已经可以满足需求,但有些人可能还会画蛇添足,增加这么两个类,而即使是为了想不写string.这样的,那也没有必需写两个方法,一个方法可以了,因为这两个方法本身就是对立的,只可能同时存在一种情况,可以进行如下改进:
1
2
3
4
5
6
7
8
9
|
static
bool
IsNullOrEmpty(
object
obj)
{
if
(obj ==
null
)
{
return
true
;
}
return
string
.IsNullOrEmpty(obj.ToString());
}
|
这样改进后,明显的IsNullOrEmpty可以用来判断所有的类型是否为Null 或者 Empty,如果需要判断不需要为Null 或者 Empty,只需调用该方法并取反即可,如:!IsNullOrEmpty("zuowenjun")