这里的数据指的大概就是字段(貌似这章有些东西也是过时了,因为现在的.NET已经发展了很久了,包括Java也是)
1、自封装字段(其实就是属性啦,过时了)
修改点:直接访问字段,但是与字段间的耦合关系逐渐变得笨拙
做法:为这个字段建立一个取值/设值函数,并且只以这些函数来访问数据
好吧,现在明白属性是怎么来的了吗,就是因为这个原因,所以有的人会干脆和你说,你不要写公共字段,直接写公共属性。
因为公共字段能做的公共属性都能做,不能做的公共属性也能做。
public string 我叫公共属性 { get; set; }
多写个这东西好用多了,以后万一有个什么反射的需要,也简单多了,举手之劳,所以忘记还有公共字段这回事吧。
2、以对象取代字段
修改点:你有一个字段,需要与其它数据和行为一起使用才有意义
做法:用对象取代字段
简单地说,你玩过DateTime这个类吗,就是系统的类,其实就是对数据的一个封装啊。
如果没有这个东西,那么你是不是要用年,月,日(就算没有时分秒吧),三个字段来表示。搞的多了自然就像自己封装一个Date类,哪天又多了个按格式输出的要求,是不是要再写个格式化函数
所以那么就把这些好基友都放在一起好了,于是DateTime就成了基友之家。(然而我们需要更多的DateTime样的基友之家)
3、将值对象改为引用对象
修改点:你从一个类衍生出许多彼此相等的实例,希望将它们替换为同一个对象
做法:将这个值对象变为引用对象
简单地说,这里所谓的值对象是指DateTime这种对象,即可以建立很多次,纯数据的传递,而所谓的引用对象是指缓存的东西,比如淘宝界面的分类数据,因为所有人看到的分类都是一样的,那么我们不需要每次都从数据库取值
缓存一下就好,不需要每次New一个分类对象,然后调用查询函数,而是去找缓存去看是否有了缓存,有了缓存,那么就调用,没有缓存那么就再从数据库里面取值。只要缓存一更改,大家看到的分类就都更改了。
好了,就是这么个意思
其中为了适应也许引用对象会根据不同的类型创建一个不同的对象,(就像有个墙类,上节课Troy教小朋友们如何搬砖砌墙,所以新建正常的墙的对象,这节课话题换了,Troy教小朋友们码长城,于是就新建一个长城对象)
当涉及到切换子类的时候,可以用这种方法使得客户端调用的时候不需要知道还有长城这个类,只需要用墙类里的工厂函数就好了,当然也许你下次还得搞个扛水泥去搞个水泥墙的类,那么在 工厂函数里再加就好了。
所以提到的一个重构方法:
将构造函数改为调用工厂函数,即
public class Wall{ public Wall(string length){ //啦啦啦 } }
改为
public class Wall{ public static Wall Create(string type){ if (type=="Great"){ return new GreatWall("一万里"); } else{ return new Wall("一米"); } } protected Wall(string length) { //啦啦啦 } } public class GreatWall:Wall { public GreatWall(string length):base(length) { //啦啦啦 } }
这种方法的用处在于客户调用不需要去知道子类,只需要知道type就行了,当然具体情况具体对待,你也可以不用这么写
然后这个所谓的引用变量的稳妥一点的做法还是要判断一下这个对象存不存在,不存在就去取值,存在就直接调用。
4、将引用对象改为值对象
是的,你没有看错,当你千辛万苦改成了值对象之后,有个需求第二天可能又会让你改回来。。
动机:因为你的引用对象很小且不可变,而且不易管理。
不可变是什么鬼?我看了《重构》这个看了半天,最后才弄明白。
还是用分类缓存来说,淘宝的缓存就是可变的,因为淘宝的缓存假如作为商家的你可以自己去去增加分类,然后刷新它,那么所有的客户得到的分类都变了。
那么不可变是就是:
我在本地把百度首页改成这样,但是你们这些人并不知道我已经在用谷歌了╮(╯▽╰)╭
换句话说,有天,马老板说咱淘宝分类就这么搞了,无论怎样就这么多分类了,不许商家去增加分类,那么,这个缓存就是不可变的了,某天他说不要那么多分类了,就假货和真货两个类的时候,那么引用对象足够小了
那么这个引用对象也就不需要了,改成值对象就好了,比如像百度一下直接作为文本,写死在页面上了。
好吧,我就是这么理解的。
正经话:引用对象就是客户公用的,当我去改动后,其他客户看到的也就变了,而值对象不是,当我改动后只有我自己这边变了。(懂了吗,我觉得自己已经讲得很清楚了)
5、以对象取代数组
修改点:你有一个数组,其中的元素代表不同的东西
做法:以对象替换数组,对于数组中的每个东西,以一个字段来表示。
换句话说,有个混蛋把DateTime的年月日写在一个int date[3];这样的东西里面,其中date[0]代表年,date[1]代表月,你是否想要打死他?
--未完待续