免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4436 | 回复: 13

[其他] 【转自酷壳】如此理解面向对象编程 [复制链接]

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
发表于 2012-12-13 16:40 |显示全部楼层
如此理解面向对象编程

2012年12月13日陈皓发表评论阅读评论 6,157 人阅读   

从Rob Pike 的 Google+上的一个推看到了一篇叫《Understanding Object Oriented Programming》的文章,我先把这篇文章简述一下,然后再说说老牌黑客Rob Pike的评论。

先看这篇教程是怎么来讲述OOP的。它先给了下面这个问题,这个问题需要输出一段关于操作系统的文字:假设Unix很不错,Windows很差。

这个把下面这段代码描述成是Hacker Solution。(这帮人觉得下面这叫黑客?我估计这帮人真是没看过C语言的代码)

  1. public class PrintOS
  2. {
  3.     public static void main(final String[] args)
  4.     {
  5.         String osName = System.getProperty("os.name") ;
  6.         if (osName.equals("SunOS") || osName.equals("Linux"))
  7.         {
  8.             System.out.println("This is a UNIX box and therefore good.") ;
  9.         }
  10.         else if (osName.equals("Windows NT") || osName.equals("Windows 95"))
  11.         {
  12.             System.out.println("This is a Windows box and therefore bad.") ;
  13.         }
  14.         else
  15.         {
  16.             System.out.println("This is not a box.") ;
  17.         }
  18.     }
  19. }
复制代码
然后开始用面向对象的编程方式一步一步地进化这个代码。

先是以过程化的思路来重构之。


过程化的方案

  1. public class PrintOS
  2. {
  3.     private static String unixBox()
  4.     {
  5.         return "This is a UNIX box and therefore good." ;
  6.     }
  7.     private static String windowsBox()
  8.     {
  9.         return "This is a Windows box and therefore bad." ;
  10.     }
  11.     private static String defaultBox()
  12.     {
  13.         return "This is not a box." ;
  14.     }
  15.     private static String getTheString(final String osName)
  16.     {
  17.         if (osName.equals("SunOS") || osName.equals("Linux"))
  18.         {
  19.             return unixBox() ;
  20.         }
  21.         else if (osName.equals("Windows NT") ||osName.equals("Windows 95"))
  22.         {
  23.             return windowsBox() ;
  24.         }
  25.         else
  26.         {
  27.             return defaultBox() ;
  28.         }
  29.     }
  30.     public static void main(final String[] args)
  31.     {
  32.         System.out.println(getTheString(System.getProperty("os.name"))) ;
  33.     }
  34. }
复制代码
然后是一个幼稚的面向对象的思路。

幼稚的面向对象编程

PrintOS.java

  1. public class PrintOS
  2. {
  3.     public static void main(final String[] args)
  4.     {
  5.         System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
  6.     }
  7. }
复制代码
OSDiscriminator.java

  1. public class OSDiscriminator // Factory Pattern
  2. {
  3.     private static BoxSpecifier theBoxSpecifier = null ;
  4.     public static BoxSpecifier getBoxSpecifier()
  5.     {
  6.         if (theBoxSpecifier == null)
  7.         {
  8.             String osName = System.getProperty("os.name") ;
  9.             if (osName.equals("SunOS") || osName.equals("Linux"))
  10.             {
  11.                 theBoxSpecifier = new UNIXBox() ;
  12.             }
  13.             else if (osName.equals("Windows NT") || osName.equals("Windows 95"))
  14.             {
  15.                 theBoxSpecifier = new WindowsBox() ;
  16.             }
  17.             else
  18.             {
  19.                 theBoxSpecifier = new DefaultBox () ;
  20.             }
  21.         }
  22.         return theBoxSpecifier ;
  23.     }
  24. }


  25. BoxSpecifier.java

  26. public interface BoxSpecifier
  27. {
  28.     String getStatement() ;
  29. }


  30. DefaultBox.java

  31. public class DefaultBox implements BoxSpecifier
  32. {
  33.     public String getStatement()
  34.     {
  35.         return "This is not a box." ;
  36.     }
  37. }


  38. UNIXBox.java

  39. public class UNIXBox implements BoxSpecifier
  40. {
  41.     public String getStatement()
  42.     {
  43.         return "This is a UNIX box and therefore good." ;
  44.     }
  45. }


  46. WindowsBox.java

  47. public class WindowsBox implements BoxSpecifier
  48. {
  49.     public String getStatement()
  50.     {
  51.         return "This is a Windows box and therefore bad." ;
  52.     }
  53. }
复制代码
他们觉得上面这段代码没有消除if语句,他们说这叫代码的“logic bottleneck”(逻辑瓶颈),因为如果你要增加一个操作系统的判断的话,你不但要加个类,还要改那段if-else的语句。

所以,他们整出一个叫Sophisticated的面向对象的解决方案。

OO大师的方案

注意其中的Design Pattern

  1. PrintOS.java
  2. public class PrintOS
  3. {
  4.     public static void main(final String[] args)
  5.     {
  6.         System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
  7.     }
  8. }
  9. OSDiscriminator.java

  10. public class OSDiscriminator // Factory Pattern
  11. {
  12.     private static java.util.HashMap storage = new java.util.HashMap() ;

  13.     public static BoxSpecifier getBoxSpecifier()
  14.     {
  15.         BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ;
  16.         if (value == null)
  17.             return DefaultBox.value ;
  18.         return value ;
  19.     }
  20.     public static void register(final String key, final BoxSpecifier value)
  21.     {
  22.         storage.put(key, value) ; // Should guard against null keys, actually.
  23.     }
  24.     static
  25.     {
  26.         WindowsBox.register() ;
  27.         UNIXBox.register() ;
  28.         MacBox.register() ;
  29.     }
  30. }
  31. BoxSpecifier.java

  32. public interface BoxSpecifier
  33. {
  34.     String getStatement() ;
  35. }
  36. DefaultBox.java

  37. public class DefaultBox implements BoxSpecifier // Singleton Pattern
  38. {
  39.     public static final DefaultBox value = new DefaultBox () ;
  40.     private DefaultBox() { }
  41.     public String getStatement()
  42.     {
  43.         return "This is not a box." ;
  44.     }
  45. }
  46. UNIXBox.java

  47. public class UNIXBox implements BoxSpecifier // Singleton Pattern
  48. {
  49.     public static final UNIXBox value = new UNIXBox() ;
  50.     private UNIXBox() { }
  51.     public  String getStatement()
  52.     {
  53.         return "This is a UNIX box and therefore good." ;
  54.     }
  55.     public static final void register()
  56.     {
  57.         OSDiscriminator.register("SunOS", value) ;
  58.         OSDiscriminator.register("Linux", value) ;
  59.     }
  60. }
  61. WindowsBox.java

  62. public class WindowsBox implements BoxSpecifier  // Singleton Pattern
  63. {
  64.     public  static final WindowsBox value = new WindowsBox() ;
  65.     private WindowsBox() { }
  66.     public String getStatement()
  67.     {
  68.         return "This is a Windows box and therefore bad." ;
  69.     }
  70.     public static final void register()
  71.     {
  72.         OSDiscriminator.register("Windows NT", value) ;
  73.         OSDiscriminator.register("Windows 95", value) ;
  74.     }
  75. }
  76. MacBox.java

  77. public class MacBox implements BoxSpecifier // Singleton Pattern
  78. {
  79.     public static final MacBox value = new MacBox() ;
  80.     private MacBox() { }
  81.     public  String getStatement()
  82.     {
  83.         return "This is a Macintosh box and therefore far superior." ;
  84.     }
  85.     public static final void register()
  86.     {
  87.         OSDiscriminator.register("Mac OS", value) ;
  88.     }
  89. }
复制代码
作者还非常的意地说,他加了一个“Mac OS”的东西。老实说,当我看到最后这段OO大师搞出来的代码,我快要吐了。我瞬间想到了两件事:一个是以前酷壳上的《面向对象是个骗局》和 《各种流行的编程方式》中说的“设计模式驱动编程”,另一个我想到了那些被敏捷洗过脑的程序员和咨询师,也是这种德行。

于是我去看了一下第一作者Joseph Bergin的主页,这个Ph.D是果然刚刚完成了一本关于敏捷和模式的书。

Rob Pike的评论

(Rob Pike是当年在Bell lab里和Ken一起搞Unix的主儿,后来和Ken开发了UTF-8,现在还和Ken一起搞Go语言。注:不要以为Ken和Dennis是基友,其实他们才是真正的老基友!)

Rob Pike在他的Google+的这贴里评论到这篇文章——

他并不确认这篇文章是不是搞笑?但是他觉得这些个写这篇文章是很认真的。他说他要评论这篇文章是因为他们是一名Hacker,至少这个词出现在这篇文章的术语中。

他说,这个程序根本就不需要什么Object,只需要一张小小的配置表格,里面配置了对应的操作系统和你想输出的文本。这不就完了。这么简单的设计,非常容易地扩展,他们那个所谓的Hack Solution完全就是笨拙的代码。后面那些所谓的代码进化相当疯狂和愚蠢的,这个完全误导了对编程的认知。

然后,他还说,他觉得这些OO的狂热份子非常害怕数据,他们喜欢用多层的类的关系来完成一个本来只需要检索三行数据表的工作。他说他曾经听说有人在他的工作种用各种OO的东西来替换While循环。(我听说中国Thoughtworks那帮搞敏捷的人的确喜欢用Object来替换所有的if-else语句,他们甚至还喜欢把函数的行数限制在10行以内)

他还给了一个链接http://prog21.dadgum.com/156.html,你可以读一读。最后他说,OOP的本质就是——对数据和与之关联的行为进行编程。便就算是这样也不完全对,因为:

Sometimes data is just data and functions are just functions.

我的理解

我觉得,这篇文章的例子举得太差了,差得感觉就像是OO的高级黑。面向对象编程注重的是:1)数据和其行为的打包封装,2)程序的接口和实现的解耦。你那怕,举一个多个开关和多个电器的例子,不然就像STL中,一个排序算法对多个不同容器的例子,都比这个例子要好得多得多。老实说,Java SDK里太多这样的东西了。

我以前给一些公司讲一些设计模式的培训课,我一再提到,那23个经典的设计模式和OO半毛钱关系没有,只不过人家用OO来实现罢了。设计模式就三个准则:1)中意于组合而不是继承,2)依赖于接口而不是实现,3)高内聚,低耦合。你看,这完全就是Unix的设计准则。

(全文完)

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-06-23 06:20:00
发表于 2012-12-13 16:53 |显示全部楼层
怎么像VB啊

论坛徽章:
4
天秤座
日期:2013-10-18 13:58:33金牛座
日期:2013-11-28 16:17:01辰龙
日期:2014-01-14 09:54:32戌狗
日期:2014-01-24 09:23:27
发表于 2012-12-13 17:43 |显示全部楼层
OO高级黑,哈哈~~~~~

论坛徽章:
26
处女座
日期:2016-04-18 14:00:4515-16赛季CBA联赛之深圳
日期:2020-06-02 10:10:5015-16赛季CBA联赛之广夏
日期:2019-07-23 16:59:452016科比退役纪念章
日期:2019-06-26 16:59:1315-16赛季CBA联赛之天津
日期:2019-05-28 14:25:1915-16赛季CBA联赛之青岛
日期:2019-05-16 10:14:082016科比退役纪念章
日期:2019-01-11 14:44:062016科比退役纪念章
日期:2018-07-18 16:17:4015-16赛季CBA联赛之上海
日期:2017-08-22 18:18:5515-16赛季CBA联赛之江苏
日期:2017-08-04 17:00:4715-16赛季CBA联赛之佛山
日期:2017-02-20 18:21:1315-16赛季CBA联赛之天津
日期:2016-12-12 10:44:23
发表于 2012-12-13 18:38 |显示全部楼层
蛋疼,以前就觉得JAVA这样的分层和设计模式感觉十分不爽,现在搞C++ 更觉得JAVA不爽,纯粹是为设计而设计,比如说数据层,好像不用hibernate 就不行,说什么抽象数据层,麻痹的,有几个项目会TM的用到多种数据库啊,用JAVA来做项目,一个字:累 !

论坛徽章:
0
发表于 2012-12-13 19:28 |显示全部楼层
Java的通病,杀鸡用屠龙刀。

这不怪他们,因为屠龙刀是标准,他们没的选择。

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
发表于 2012-12-13 22:02 |显示全部楼层
面向对象很好啊,面向过程也很好,表驱动也很好。。。

各有各的用途。

要反对的是过度设计,如此而已。
(事实上,所举OO例子在一定环境下是正确的设计,而且是经典的OO设计)

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
发表于 2012-12-13 22:03 |显示全部楼层
Java是个S/B语言。真不理解为什么为会那么多人喜欢它。

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
发表于 2012-12-14 01:48 |显示全部楼层

OO高级黑[举的例子], 强烈同意,o(∩_∩)o 哈哈

论坛徽章:
0
发表于 2012-12-14 07:16 |显示全部楼层
shan_ghost 发表于 2012-12-13 16:40
如此理解面向对象编程

2012年12月13日陈皓发表评论阅读评论 6,157 人阅读   


没有几十个 if-else 就随意 OO 纯粹是闲得蛋疼。

论坛徽章:
4
天秤座
日期:2013-10-18 13:58:33金牛座
日期:2013-11-28 16:17:01辰龙
日期:2014-01-14 09:54:32戌狗
日期:2014-01-24 09:23:27
发表于 2012-12-14 09:57 |显示全部楼层
回复 6# folklore


    此贴必须顶,没有最完美的设计,只有最恰当的方案;没有最优化的算法,只有最合适的选择。

当人们不再迷恋OO,不再迷恋模式,OO跟模式就可以上位了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP