享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

友元在模式中的运用

Posted on 2005-02-01 14:37  idior  阅读(3725)  评论(17编辑  收藏  举报
       记得在C++中有友元这个概念,具体指一个类的朋友(类或函数)可以访问该类的私有成员,最典型的例子就是operator重载。

    咋看上去友元使得类的私有成员暴露以致影响了类的安全性(封装),但是实际上它反而保证了类的安全。让一个朋友访问你比让所以的人访问你安全的多。比如你有一份私有文件,想让你的朋友查看,如果通过友元,你可以很方便的让你的朋友访问到那份私有文件。如果没有友元,那你怎么办?只能将这份文件变成public,那样不仅你的朋友可以访问它,任何人都可以访问它了,类的安全性受到了破坏。

    也就是说友元提供了一种约束,失去友元就少了这么一种约束规则。
    那么我们看看在模式中那些地方可以使用到它。
State模式中的Contextstate就应该只能被ConcreateState所修改,而不能被外界所修改,这也是State区别与Stratage的一个重要方面,如何表现出这种约束?通过友元就很简单了,将Contextstate设为私有,ConcreateState设为Context的友元就可以了,这样就实现了前面提到的约束。详见我另一篇随笔。 
    而在javac#中似乎并没有提供这么一种方法。那么怎么办?
    一种办法就是在
Context中加入SetStatepublic方法,这样做约束就没了。
    还有一种方法,利用反射,利用反射你可以获得一个类的私有成员,不过效率太低,语义也显得复杂。

    更深入的应用,在
O/R mappingDomainObjectMapper需要构造出DomainObject,这样势必会设置DomainObject的私有变量。如果没有友元,那你必须提供DomainObject所以私有变量的设值函数,而你又显然不愿意这样(严重破坏DomainObject的封装性)。如果有友元就简单的多了。 

    友元是不是就完美了呢?

    不是的,就拿第一个例子来说,你的朋友确实是可以访问你的私有文件了,但是你想让他看你的日记吗?友元使得他有了这个权利!所以如果低粒度的考虑,友元还要再进行细分,细分成每个私有成员的友元,不过这样好像太麻烦了。

    可是为什么java C#连友元都不支持呢?