又见手把手系列-面向对象扫盲-通俗的OO第一弹-【封装】

最近针对OO有了太多的讨论,太多的误会,太多的不理解。让我来一次性解决什么是对象,为什么要面向对象的问题吧,这是第一篇。

所谓面向对象的编程、设计、思想。我们用大白话来说。

面向对象就是用 某物(对象),是什么(类),有什么(对象的状态),能干什么(方法)的方式来描述程序的方法。这就是面向对象。

面向对象的程序的特征,封装性:也就是某物状态的改变,必须是他自己的行为来改变。

打个比方,我(人类),有钱(有什么),你(人类),要找我借钱(能干什么)。于是

class Man()
{
    private int money;
    public int Money
    {
        get{return money}
        set{money=value}
    }
    public void Borrow(Man Target,int Howmuch)
    {
        money+=Howmuch;
        Target.Money-=Howmuch;
    }
}
就是这个样子。这样子的写法是不对的,这样破坏类的封装性,我们绕过了Man的对象,直接去操作了对象的状态。这完全是强盗逻辑,跟你直接到我钱包里掏钱一样不可饶恕。所以,借钱这个动作还需要我来参与,你找我借钱,而我,要借给你钱。我们修改一下类的代码。我们给Man类增加一个Lend的方法,以封装在借出钱的时候对自身状态的改变。然后借钱的行为也要更改了。
class Man()
{
    private int money;
    public int Money
    {
        get{return money}
        set{money=value}
    }
    public bool Lend(int Howmuch)
    {
        if(Howmuch<money)
        {
            money-=Howmuch;
            return true;
        }else
        {
            return false;
        }
    }
    public void Borrow(Man Target,int Howmuch)
    {
        money+=Howmuch;
        Target.Lend(Howmuch);
    }
}
这样子的代码就是满足了封装性的原则,注意,封装既是特征,也是必须满足的条件,如果破坏了封装性原则那就是破坏了OO的原则。

这里回到了一个很实际的问题,失血模型为什么不OO。
我们定义了Book类,封装了Book的状态(属性)。如果我们用一个BookManager类去Save这本书(典型的失学模式的做法)。那么,我们在BookManager中如何保存?很多人在BookManager.Save里读取Book的属性,生成SQL,写数据库,返回执行结果。这样子OO么?不OO,因为这种做法完全破坏了封装性的原则。就跟之前借钱的例子一样。所以我们要在Book类增加一个Save方法,这个方法是用来维护Book类本身的状态的。而很多的ORM也能够给我们的类注入这类方法,使我们的的类具备持久化的能力。这样Book的属性,如何在数据库里存储,如何读取,如何删除都是Book自身来负责,因为在数据库里关于Book 的记录都是属于Book的状态,所以都需要Book自身来封装,使其透明化。


很多人在之前我写的Book.Save是否OO的话题里面说,觉得Book.Save方法仅仅是换了个位置。但是哪里知道,这个小小的改变却是一个原则性的问题。而至于双鱼座觉得在Save里加入上下文的参数更加符合实际情况,我个人觉的加和不加对Book类是否符合OO的原则没有太大的影响。
但是有和没有确是天壤之别了。

封装是保证系统的高内聚低耦合的很重要的设计原则。
还是用Book作为例子,如果你的Book需要添加一个属性来表示新的状态(换句俗话就是你在数据库里加列了,数据库变化了)。如果你的Book类自己维护了自己的持久化状态,那么你就只需要修改Book类的持久化状态的方法。如果你使用的VS2005的话,使用重构功能一次性就能把所影响到的地方全部修改(java的用Eclipse也有同样的功能)。而如果没有封装的话。那么你可能需要改的还有BookManager,如果在其他地方还用到了Book,可能还有数不清的代码在等着你改。为什么会麻烦,因为没有了封装,类和类之间产生了耦合。

下一章我们会接下来谈继承(也包括接口的Implement)

posted on 2007-09-21 16:19 亚历山大同志 阅读(5156) 评论(57)  编辑 收藏 所属分类: 手把手系列

评论

#1楼  2007-09-21 16:46 makeliving      

支持,抓紧时间。
讲解更加单纯于思想,尽量不要结合工具(不是语言),我个人感觉有些工具封装了很多的东西,反而阻碍了入门程序员的学习。OO很重要,讨论OO比语言之争有意义的多,从这个角度来说还是进步了。   回复  引用  查看    

#2楼  2007-09-21 16:48 老翅寒暑      

我认为有待商榷,Book.save如果只针对一种存储媒介,从实用的角度看也可以接受,但是如果我们的Book不仅可能存放在XmlPersistance中,也可能放在DbPersistence中呢?
最佳的做法当然是把Book.save取消掉。当然Book.save不取消也可以,我们就会被迫加一个参数了Book.save(PersistenceType.xml)。可是这样真的没有问题吗?如果我们增加了一个TextPersistence呢?再在5个月之后加入一个CSVPersistence和BinaryPersistence呢?
显然Book.save就不满足要求了。遵循KISS(Keep It Simple and Stupid)的原则,Book.save也许算是OO,但是至少不彻底----把别人的事情也做了。
其实这里归根到底涉及的是一个语法问题,Book是一个名词,Save是一个及物动词,到底程序中要用somebody save book还是book saved by somebody。我倾向于前者。
另外,对于Book这样一类纯被动的物品类,建议还是采用java的概念,把它做成一个POJO(ms阵营好像没有对应的词哦)   回复  引用  查看    

#3楼  2007-09-21 16:53 徐少侠      

老兄啊
给你发了留言希望你支持一下我去开个团队。
咋就没反应呢?

最近是不是吵架吵上瘾了?
不过我的劲头是给调上来了
  回复  引用  查看    

#4楼  2007-09-21 16:54 makeliving      

条条大路通罗马,做程序也是这样,使用OO的思想可以,适用面向过程思想也可以完成,如果单纯的基于此来判断那种好那种不好是没有意义的,我是说结果都是一样解决了问题。
但是如果需求产生了变化,新的问题就会产生,如何高效、方便的应对新产生的问题,OO这个时候才真正起作用。   回复  引用  查看    

#5楼 [楼主] 2007-09-21 16:55 亚历山大同志      

@老翅寒暑
Store的位置不一样了,功能确还是和语义一致的。加了一个带参数无不妥,不然干嘛要重载方法?
就算是因为存储位置的不一样也不叫
===========================
但是至少不彻底----把别人的事情也做了。
===========================
我认为针对你提出的问题,用重载方法完全能解决,至于具体要怎么Save,那是去Call Book to Save it 的类的行为去完成的事情。

  回复  引用  查看    

#6楼 [楼主] 2007-09-21 16:55 亚历山大同志      

@徐少侠
不是想吵架,是想把事情说清楚而已   回复  引用  查看    

#7楼 [楼主] 2007-09-21 16:59 亚历山大同志      

@makeliving
无数种方法都能解决问题,其中必有好坏之分,
==========================================
如何高效、方便的应对新产生的问题,OO这个时候才真正起作用。
==========================================
正如这句话,OO的目的就是为了高效,方便的解决问题。

才说到封装,且待我慢慢道来   回复  引用  查看    

#8楼  2007-09-21 17:00 念时      

你讲解得很通俗,每次读讲OO的文章,都多少能有些收获。期待你的下一篇……   回复  引用  查看    

#9楼  2007-09-21 17:29 Oliver UU [未注册用户]

行,有点意思!   回复  引用    

#10楼  2007-09-21 17:29 徐少侠      

周末抽空画类图
下周来详细讨论
Book.Save VS. Helper.Save(oBook) 问题

OO人人会说,看样子深入理解并能熟练使用的不多

不过,天晓得等这波潮水退了以后会不会发现自己才是那个裸泳的?

管他了,权当学习。

  回复  引用  查看    

#11楼  2007-09-21 17:40 老翅寒暑      

@亚历山大同志
要用最简单的方法,我不想增加一个DbPersistence之后再去修改PersistenceType。
有基类IPersistence.save(Book)是最简单的方法。
即使要重载也不是重载Book,难道出一个新的BookInDB或者BookInXML?
再次强调KISS原则。   回复  引用  查看    

#12楼  2007-09-21 18:05 武眉博<活靶子.Net>      

通俗   回复  引用  查看    

#13楼  2007-09-21 18:20 紫色阴影      

写得不错
不过封装不仅仅是这一点点啊,它是OO最重要的一块,除了封装属性还有封装行为甚至更多而不只是数据隐藏。有句很有名的话:Encapsulate what varies!
期待LZ能介绍更多   回复  引用  查看    

#14楼  2007-09-21 18:22 Kingthy      

观点同@老翅寒暑

假如有A报摊和B报摊,现有一份报纸C,你说C送哪个报摊好呢?根据你的文章,你的选择只有一种就是C内部定义的Save方法.即不是放到A就是B报摊(因为C是一个行为者,所以只能决定一种情况).而如果再继续分出一个BookManager,则此时C的最终去处就是由BookManager来决定的.所以BookManager可以根据情况来决定送给A还是B了..也许你可以说也可以在C的内部方法Save做条件处理啊,但假如不只是有限的报摊A和B,而是有很多(现实就是这样有很多不确定性因素)那你这里的Save方法又怎么办呢?大家都知道现实的情况是如果一份报纸发版后是不可能再重更改印刷的,而行为者由BookManager施发则不同,我们可以实现不同的Manager(就好比添加不同的送报员).因为不会破坏Book的数据定义....   回复  引用  查看    

#15楼  2007-09-21 18:39 紫色阴影      

同意上面的
save方法只是做持久化,感觉不应该归属为book的domain logic,而且涉及到持久化的操作放在domain object不容易复用,所以save方法放在book类如果只是为了看起来OO的话没有必要
所以设计持久化的操作还是抽象出来,由Manager或者Service来执行为好,这样Manager层就负责持久化逻辑,事务协调或者多对象的交互。

@老翅寒暑
.NET下叫POCO -- Plain Old CLR Object   回复  引用  查看    

#16楼  2007-09-21 18:59 金色海洋(jyk)      

>>面向对象就是用 某物(对象),是什么(类),有什么(对象的状态),能干什么(方法)的方式来描述程序的方法。这就是面向对象。

如果这样的话,能不能这样来理解:

数据库里的表(属于什么类别呢?没想起来),有字段(或者是有数据)(有什么),要往里添加记录(能干什么)。

这样是不是能够弄一个 表.Insert 表.Update 呢?

Book.Save Book 没有保存的功能,那么表有没有呢?



在你们的眼里,书、人、车、新闻、聊天室里的人房间、产品信息等等,这些都是对象。(我没理解错吧)


在我眼里,表、字段、代码等等,这些也是对象。
如果成立的话,那么上面说的这些都是一个事物 —— 表。
他们的属性就都是字段。

这样 表.Save 就成立了,呵呵。

为什么要这样理解呢?因为自然界里的对象实在是太多了,而数据库、代码就简单多了,就是添加、修改、删除、查询、分页、统计、报表、打印。有数得这么几种,再多也多不了几种,呵呵。

数据库里就是表、字段、视图、存储过程,再加上函数,SQL语句。

PS:希望不要让某些人生气。


  回复  引用  查看    

#17楼 [楼主] 2007-09-21 20:59 亚历山大同志      

@老翅寒暑
无论怎么做,只要不违反OO的原则就行了,解决这类问题的经验集合,其实就是设计模式。那是我们最后来讨论的问题   回复  引用  查看    

#18楼 [楼主] 2007-09-21 21:08 亚历山大同志      

@紫色阴影
@Kingthy
这里为了通俗,只是用了最简单的方式,但是万事都是由简入繁。
作为OO的基本原则,封装是基本要求,解决复杂问题在设计模式中有很多的方法可以实现,但是不是这里要讨论的问题,所以这个结构只是最简单的基础,在实际情况下有不同的需求,按么我们抽象出来的结果也有所不同,你们把讨论的基础环境都改变了再来讨论这个问题也就太牵强了,如果是明说了需要持久化到不同的地方,我们抽象出来的东西肯定就不是这个样子了。
无论如何,封装不是为了OO而OO,而是基础原则,如果你在解决问题的时候一个类没有满足封装性,那么很显然的,他和其他类肯定发生了耦合。
当然这样子的耦合在一定程度上是允许的,比如说Inner Class和Outer Class之间是可以有一定的耦合的。
总而言之,这里强调了,通俗上什么是封装,为什么要封装,封装的重要性。如果吹毛求疵的要求一个Hello World适应所有的情况,那么就没人能写出Hello world了   回复  引用  查看    

#19楼 [楼主] 2007-09-21 21:16 亚历山大同志      

@金色海洋(jyk)
你这样子抽象出来就是通用的DAL了,再实现了Mapping的功能就是ORM咯,其实最朴素的ORM的需求就是这么抽象出来滴   回复  引用  查看    

#20楼  2007-09-21 22:01 金色海洋(jyk)      

原来我一直用的都是“ORM”呀。
我都没觉得是,不过最近倒是有点体会了,感觉自己做的是把 控件(文本框、下拉列表框等)和字段对应起来了。然后就可以 表单.Save() 。了。
简单的可以直接用我写的表单控件。
我做的真的是ORM吗?   回复  引用  查看    

#21楼  2007-09-21 22:03 Kingthy      

@金色海洋(jyk)
用STS说的评论回答你足以。。。
“book.Save是什么意思, 是把編程里的數據保存了, 還是描述現實中把書放回書架??沒搞清編程和現實的區別,根本不能談OO.”

@亚历山大同志
或者建议你看看设计模式的书籍会有好处,一味的封装并非是好事   回复  引用  查看    

#22楼 [楼主] 2007-09-21 22:14 亚历山大同志      

@Kingthy
你曲解了设计模式的目的,纵观23中经典设计模式没有一个是破坏了封装性原则的。

设计模式最与设计的最大贡献在于针对打破传统继承体系的禁锢,或许你再重新翻翻设计模式的书看看是否有新的发现。仔细看看所有设计模式的类图你会发现,设计模式和封装是不冲突的。

都这么心急,害我把准备下一张说的都说出来了以部分..............汗.............   回复  引用  查看    

#23楼  2007-09-21 22:21 Kingthy      

@亚历山大同志
呵呵,看来我们没有必要再继续讨论下去了.

PS:看来我也猜到你的下一章的教程会是怎样一个程度了.:)   回复  引用  查看    

#24楼  2007-09-21 23:12 www.oxsoft.cn [未注册用户]

晕。。。。。   回复  引用    

#25楼 [楼主] 2007-09-21 23:22 亚历山大同志      

@Kingthy

在之前讨论OO的Post里面,务虚的居多,大多数无谓的义气之争都是从务虚开始的。虚无缥缈的文字游戏实在是很无趣的,一大堆"理论",引经据典,其实都不如简单的几行代码来得实在。我之所以写这么个Post就是从简到繁,代码结合理论来阐述问题。否则看似高深的讨论,其实什么都没讨论出来,最后就是两头都不得罪的中庸答案比较讨好,其实也就是告诉大家,怎么弄都行,该杂杂地,那么讨论半天不是白说了吗?最后弄得似懂非懂,貌似明白了其实也没得到什么。我觉得大家应该先假定一个需求,从简单慢慢到复杂,再用OO的方法去解决这些难题(非经典OO,因为会用到接口--设计模式必备弹药)。如果有兴趣就继续看下去,慢慢的我们假设的情况会越来越复杂,慢慢的也会越来越有看头。   回复  引用  查看    

#26楼  2007-09-22 00:08 saucer [未注册用户]

是Borrow还是Lend,应该是程序所在域的概念性问题,跟你这里所要倡议的封装无关,而且你完全可以修改Borrow方法使用类似Lend里面的实现

封装是把实现的细节隐藏起来,你这里的细节是什么?money的值和Borrow或Lend的逻辑

你的类实现的最大问题在于

public int Money
{
set{money=value;}
}

你大概不愿意使用Man实例的客户端代码直接操作Money吧,你也许可以让外面知道你有多少钱,但对钱数值的改变应该通过其他行为,譬如Borrow或Lend才能实现   回复  引用    

#27楼  2007-09-22 01:00 壁虎      

楼上的内容。。。
难道博客园开始限制言论了?这个不太好吧,都要靠大家自觉嘛,不停的限制最后就搞成**#**的怪异语言了。   回复  引用  查看    

#28楼  2007-09-22 01:13 壁虎      

是楼上的楼上了   回复  引用  查看    

#29楼  2007-09-22 06:40 金色海洋(jyk)      

其实对于我来说 OO不OO的根本就无所谓。
只要能够达到:代码少、易于理解、易于维护、冗余代码极少、易于扩展、易于多人配合,当然最重要的是要能够实现客户的要求。

这样就可以了。至于是OO的还是过程的,管他呢!为什么一定要用OO来限制自己呢?

另外不能把表、字段、视图、存储过程看成对象吗?不能针对他们封装吗?

不能把保存数据的一段代码看成对象吗?不能针对这个来抽象吗?

就像我在“第一步抽象”里写的那个例子里的代码,

保存数据的一段代码(是代码或者程序),有语句、数组、字符串(有什么),能够往数据库里添加记录(能干什么)。


而在“第三步抽象”里面就对这些代码进行了“提炼”(还是先不用抽象的好)。让它可以应对多个表。

其实“第三步抽象”里写的是一个思路,而不是一个可以工作的程序。


我认为 book.Save是把編程里的數據保存了的意思。

程序就是程序,现实就是现实,无法一一对应的。

  回复  引用  查看    

#30楼  2007-09-22 10:06 LeadNT [未注册用户]

如果我们用一个BookManager类去Save这本书(典型的失学模式的做法)。那么,我们在BookManager中如何保存?很多人在BookManager.Save里读取Book的属性,生成SQL,写数据库,返回执行结果。这样子OO么?不OO,因为这种做法完全破坏了封装性的原则。


从这句话我可以看出楼主以前应该学习不错,教条主义,死记硬背下出来的杰出人才;

楼主能这么说,我很替楼主欣慰,因为楼主还有很大的上升空间;
但楼主这么说,我又很是担心,这会误导多少后来兵啊.
  回复  引用    

#31楼  2007-09-22 10:38 补丁      

模型建的就不好
人有钱,是拥有一定数量的钱
钱也是对象,不是int   回复  引用  查看    

#32楼  2007-09-22 10:38 kisskiki [未注册用户]

◎楼上的
说说你的想法嘛?为什么说是死记硬背了?   回复  引用    

#33楼  2007-09-22 10:39 kisskiki [未注册用户]

◎应该是leadnt   回复  引用    

#34楼 [楼主] 2007-09-22 10:57 亚历山大同志      

@saucer
多了个Set,是我的错,但是之所以限制只能够通过借和借出这两个方法才能改变钱的数量的话是因为这两个行为确实有其明确的语义,而如果通过修改属性Money确实也能够达到封装的目的,但是语义不明确了,我如果只看到Money属性不知道他能干什么,程序的代码具备自我描述的能力是大家的共识,所以我用了两个方法来封装借和借出两个有不同语义的行为,这样子更加明确也能够让使用到这个类的程序员一眼就能够知道这个类是什么,有什么,能干什么。
最后多谢指正。
  回复  引用  查看    

#35楼  2007-09-22 11:36 bluebirdzx [未注册用户]

关于 OO 权威的资料很多,大家没有必要在这里去解释什么,让别人去怎么面向对象,在博客园最好能写一些实践经验之类的最好。一个是对所说的话要负责,否则,最好不要发到首页。新手看了都不知要怎么办了,仁者见仁智者见智。   回复  引用    

#36楼  2007-09-22 11:49 roydu/LeadNT/小宇哥哥 [未注册用户]

@bluebirdzx


同意这位兄弟的   回复  引用    

#37楼  2007-09-22 12:13 kisskiki [未注册用户]

--引用--------------------------------------------------
bluebirdzx: 关于 OO 权威的资料很多,大家没有必要在这里去解释什么,让别人去怎么面向对象,在博客园最好能写一些实践经验之类的最好。一个是对所说的话要负责,否则,最好不要发到首页。新手看了都不知要怎么办了,仁者见仁智者见智。
--------------------------------------------------------
看了不知道该怎么办?你要求别人写实践经验,自己不去实践?

这样值得大家关注和探讨的问题(很多想提高自己设计能力的人都会想看的吧?)如果不发到首页,有多少人来看了?有多少人讨论了?
个人觉得没什么的。   回复  引用    

#38楼  2007-09-22 12:35 bluebirdzx [未注册用户]

用c++写了6年的程序了,但是我不敢随便说面向对象,oo思想,太深奥了,自己文笔不好,也不敢写这些。看了别的那些流畅的文笔非常羡慕。   回复  引用    

#39楼  2007-09-22 12:38 bluebirdzx [未注册用户]

你在这几篇文章中都有讨论,是一个很好学的好孩子,继续努力,呵呵   回复  引用    

#40楼  2007-09-22 12:43 bluebirdzx [未注册用户]

不是说 亚历山大,呵呵,呀历山大的名字就和他的人一样,非常好。   回复  引用    

#41楼  2007-09-22 13:07 xiao_p      

让我来一次性解决什么是对象,为什么要面向对象的问题吧,这是第一篇。
>>好像很多大牛都不敢这么说。呵呵
不过倒是支持楼主这样的做事态度。


  回复  引用  查看    

#42楼  2007-09-22 13:09 kisskiki [未注册用户]

--引用--------------------------------------------------
bluebirdzx: 关于 OO 权威的资料很多,大家没有必要在这里去解释什么,让别人去怎么面向对象,在博客园最好能写一些实践经验之类的最好。一个是对所说的话要负责,否则,最好不要发到首页。新手看了都不知要怎么办了,仁者见仁智者见智。
--------------------------------------------------------
仅仅从你说的要写一些实践经验的言论来看,难以看出你是写了6年的程序了。
没有其他意思,别冲动~~~~:)~~~

思想不是由人来归纳和发挥的么?深奥只是因为你提到的“无法表达出来而已”。至于能否以浅显易懂的语言来表达出来就看各人的功力了,如果你非得要求别人得有实践经验论证,又得浅显易懂,还得规范合理,有点强人所难吧?

流畅的文笔通常来源于较好的逻辑思维能力。有了较好的逻辑思维能力可以帮助你理解oo。

从你的评论可以看出,你可以算是很有经验的代码写手了,好好努力,通过写技术文章锻炼你的逻辑思维!进而加深对oo的理解,也让我们这些孩子通过你的文章少走弯路。嘻嘻。

汗,我的验证码居然是9547
  回复  引用    

#43楼  2007-09-22 13:28 Jeffrey Hua [未注册用户]

"封装是保证系统的高内聚低耦合的很重要的设计原则。"
封装的好坏一般可以通过high cohesion and low coupling来判断.
但是封装并不能保证系统的high cohesion and low coupling.
另外面向对象中有两个主要分支:class based OO vs prototype based OO.
只是因为现在应用主流的语言过分强调了class,所以使得大家一想起OO就想起类了.
我个人比较同意一种观点:把类当成是实现时的一种package code的一种方法.
事实上现在越来越强调的interface比较符合这种理解方式.一个类可以实现多个interface.



  回复  引用    

#44楼 [楼主] 2007-09-22 13:43 亚历山大同志      

其实越是写程序越是会越来越怀疑以前所以为自己掌握的自认为经典的理论人后就会反过头来回锅一次,个人觉得这并不是什么不好的事情,每一次回锅都让自己对这些基础理论的认识更加的深刻。
学习也许就是在这种反复的过程当中不断进步的吧。   回复  引用  查看    

#45楼  2007-09-22 14:45 oxsoft.cn [未注册用户]

鉴定完毕   回复  引用    

#46楼  2007-09-22 14:46 oxsoft.cn [未注册用户]

鉴定完毕!
楼主有理,大家也有理,只有我没理。   回复  引用    

#47楼  2007-09-22 15:25 94 [未注册用户]

public void Borrow(Man Target,int Howmuch)
{
money+=Howmuch;
Target.Lend(Howmuch);
}
从这代码就看出态度问题,轻浮草率   回复  引用    

#48楼  2007-09-22 20:06 木野狐(Neil Chen)      

从 OO 的角度讲, Book.Save() 不对的,因为持久化不属于领域模型应该负责的动作之一;

但是从实现的层面讲,Book.Save() 是 Active Record 模式的写法,也挺方便,但扩展起来比较局限;

这个问题不知道为什么讨论的这么复杂。   回复  引用  查看    

#49楼  2007-09-22 20:10 木野狐(Neil Chen)      

@蛙蛙池塘

XxxxManager 只是为了实现而发明的,并不是真正的领域模型。   回复  引用  查看    

#50楼  2007-09-22 21:43 蛙蛙池塘      

我刚才把我的评论删除了,不好意思   回复  引用  查看    

#51楼  2007-09-23 00:39 win yee [未注册用户]

我以为Book.Save(),BookManager.Save(Book)二者都符合OO封装原则.二者毫无差别,差别在于实际运用环境之中.
OO是把问题领域分解为对象,以及对象之间的协作.对象是包括状态与行为,而状态一般由行为来维护,这就是所谓的封装啦.但是封装并不是不让其他对象修改其状态,而是说不能直接修改.你修改我的状态我得知道符不符合我的要求.
封装是封装细节,也可以提供一个粗接口,封装还可以隐藏对象的实际创建过程.封装也只是OO的其中一个精神.OO的目的为软件开发而服务的,并不是一个学术课题.脱离实际的OO有什么用呢?
还有,OO也并不是只有封装.
我所以,我不明白楼主说的GOF如何破坏了封装,蛮值得关注的.
  回复  引用    

#52楼  2007-09-23 00:51 win yee [未注册用户]

"而如果没有封装的话。那么你可能需要改的还有BookManager,如果在其他地方还用到了Book,可能还有数不清的代码在等着你改。为什么会麻烦,因为没有了封装,类和类之间产生了耦合"
-------------------------------------------------------------
我对楼主这句话不是很明白,我以为BookManager.Save()也是一种封装,它封装了Book的数据访问逻辑.如果Book.Save()能封装好,BookManager.Save()同样也能封装好.用不着到处改代码吧.
运用存乎于心呀.   回复  引用    

#53楼  2007-09-24 12:00 徐钢      

不好意思,本人才疏学浅,问一下

前面
if(Howmuch<money)
{
money-=Howmuch;
//这里是如果自己的钱比要借的多就借,并减去得到自己剩的钱
return true;
}
后面
public void Borrow(Man Target,int Howmuch)
{
money+=Howmuch;
//money=money+Howmuch; 又把自己的钱加上借出去的,啥意思?


  回复  引用  查看    

#54楼  2007-09-24 18:07 nctaowen [未注册用户]

没有绝对的好的封装。如何封装取决于你要解决的问题的角度。而且要注意到,除了tell instead of ask之外,还有一个原则是single responsiblity。如果user既要负责领域逻辑又要负责存储逻辑,那么就违反了这个原则。user这个对象最好能够支持save和load这些操作,我同意。但是我并不同意把这些concern放到同一个类中来做。比如说,向hibernate那样,生成一个proxy,然后把两个concern的解决代码叠加到同一个对象上,但是彼此并不知道对方的实现。   回复  引用    

#55楼  2007-09-25 14:20 张子阳.      

对你的文章暂不做评论,我只是觉得你这个人太可爱了   回复  引用  查看    

#56楼  2007-09-26 19:24 cnxmouse [未注册用户]

为什么不这样呢?
class book{

...
public boolean Save(BookManager BMer){
if(可以保存了?)
BMer.Save(this);
else
throw error; //例如某个关键属性值为空
}

}

BookManager 有很多,对于book来说它并不知情,而该如何的保存自己,它更不知道,也不需要知道.
而对于BookManager 来说,他的职责在于根据系统配置把book保存到正确的位置,他不可能去检查本次保存的book是否合法.
各自处理好自己的工作,不要去多管"闲事",也不要把自己的事情推到别人头上,   回复  引用    

#57楼  2007-11-13 00:44 对象辅导员 [未注册用户]

第二篇什么时候出来啊?哈哈   回复  引用    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接:
所属专题: 关于面向对象的讨论
 


导航

公告

鉴于很多TX投诉黑色背景杀伤眼球,遂换个容易阅读的
<2007年9月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

统计

与我联系

搜索

 

常用链接

留言簿(28)

我参加的小组

我的标签

随笔分类(82)

随笔档案(82)

相册

朋友的Blog

同事的Blog

最新随笔