从一些简单代码实例彻底理解面向对象编程思想|OOP本质是什么?

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

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

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19


public class PrintOS

{

    public static void main(final String[] args)

    {

        String osName = System.getProperty("os.name") ;

        if (osName.equals("SunOS") || osName.equals("Linux"))

        {

            System.out.println("This is a UNIX box and therefore good.") ;

        }

        else if (osName.equals("Windows NT") || osName.equals("Windows 95"))

        {

            System.out.println("This is a Windows box and therefore bad.") ;

        }

        else

        {

            System.out.println("This is not a box.") ;

        }

    }

}

然后开始用面向对象的编程方式一步一步地进化这个代码。

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

过程化的方案


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34


public class PrintOS

{

    private static String unixBox()

    {

        return "This is a UNIX box and therefore good." ;

    }

    private static String windowsBox()

    {

        return "This is a Windows box and therefore bad." ;

    }

    private static String defaultBox()

    {

        return "This is not a box." ;

    }

    private static String getTheString(final String osName)

    {

        if (osName.equals("SunOS") || osName.equals("Linux"))

        {

            return unixBox() ;

        }

        else if (osName.equals("Windows NT") ||osName.equals("Windows 95"))

        {

            return windowsBox() ;

        }

        else

        {

            return defaultBox() ;

        }

    }

    public static void main(final String[] args)

    {

        System.out.println(getTheString(System.getProperty("os.name"))) ;

    }

}

然后是一个幼稚的面向对象的思路。

幼稚的面向对象编程

PrintOS.java

1

2

3

4

5

6

7


public class PrintOS

{

    public static void main(final String[] args)

    {

        System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;

    }

}

OSDiscriminator.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24


public class OSDiscriminator // Factory Pattern

{

    private static BoxSpecifier theBoxSpecifier = null ;

    public static BoxSpecifier getBoxSpecifier()

    {

        if (theBoxSpecifier == null)

        {

            String osName = System.getProperty("os.name") ;

            if (osName.equals("SunOS") || osName.equals("Linux"))

            {

                theBoxSpecifier = new UNIXBox() ;

            }

            else if (osName.equals("Windows NT") || osName.equals("Windows 95"))

            {

                theBoxSpecifier = new WindowsBox() ;

            }

            else

            {

                theBoxSpecifier = new DefaultBox () ;

            }

        }

        return theBoxSpecifier ;

    }

}

BoxSpecifier.java

1

2

3

4


public interface BoxSpecifier

{

    String getStatement() ;

}

DefaultBox.java

1

2

3

4

5

6

7


public class DefaultBox implements BoxSpecifier

{

    public String getStatement()

    {

        return "This is not a box." ;

    }

}

UNIXBox.java

1

2

3

4

5

6

7


public class UNIXBox implements BoxSpecifier

{

    public String getStatement()

    {

        return "This is a UNIX box and therefore good." ;

    }

}

WindowsBox.java

1

2

3

4

5

6

7


public class WindowsBox implements BoxSpecifier

{

    public String getStatement()

    {

        return "This is a Windows box and therefore bad." ;

    }

}

他们觉得上面这段代码没有消除if语句,他们说这叫代码的“logic bottleneck”(逻辑瓶颈),因为如果你要增加一个操作系统的判断的话,你不但要加个类,还要改那段if-else的语句。

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

OO大师的方案

注意其中的Design Pattern

PrintOS.java

1

2

3

4

5

6

7


public class PrintOS

{

    public static void main(final String[] args)

    {

        System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;

    }

}

OSDiscriminator.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22


public class OSDiscriminator // Factory Pattern

{

    private static java.util.HashMap storage = new java.util.HashMap() ;

    public static BoxSpecifier getBoxSpecifier()

    {

        BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ;

        if (value == null)

            return DefaultBox.value ;

        return value ;

    }

    public static void register(final String key, final BoxSpecifier value)

    {

        storage.put(key, value) ; // Should guard against null keys, actually.

    }

    static

    {

        WindowsBox.register() ;

        UNIXBox.register() ;

        MacBox.register() ;

    }

}

BoxSpecifier.java

1

2

3

4


public interface BoxSpecifier

{

    String getStatement() ;

}

DefaultBox.java

1

2

3

4

5

6

7

8

9


public class DefaultBox implements BoxSpecifier // Singleton Pattern

{

    public static final DefaultBox value = new DefaultBox () ;

    private DefaultBox() { }

    public String getStatement()

    {

        return "This is not a box." ;

    }

}

UNIXBox.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14


public class UNIXBox implements BoxSpecifier // Singleton Pattern

{

    public static final UNIXBox value = new UNIXBox() ;

    private UNIXBox() { }

    public  String getStatement()

    {

        return "This is a UNIX box and therefore good." ;

    }

    public static final void register()

    {

        OSDiscriminator.register("SunOS", value) ;

        OSDiscriminator.register("Linux", value) ;

    }

}

WindowsBox.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14


public class WindowsBox implements BoxSpecifier  // Singleton Pattern

{

    public  static final WindowsBox value = new WindowsBox() ;

    private WindowsBox() { }

    public String getStatement()

    {

        return "This is a Windows box and therefore bad." ;

    }

    public static final void register()

    {

        OSDiscriminator.register("Windows NT", value) ;

        OSDiscriminator.register("Windows 95", value) ;

    }

}

MacBox.java

1

2

3

4

5

6

7

8

9

10

11

12

13


public class MacBox implements BoxSpecifier // Singleton Pattern

{

    public static final MacBox value = new MacBox() ;

    private MacBox() { }

    public  String getStatement()

    {

        return "This is a Macintosh box and therefore far superior." ;

    }

    public static final void register()

    {

        OSDiscriminator.register("Mac OS", value) ;

    }

}

作者还非常的意地说,他加了一个“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的设计准则

相关阅读:什么是工程师文化?各位工程师是为什么活的?作为一个IT或互联网公司为什么要工程师文化?

相关阅读: 对程序员有用:2017最新能上Google的hosts文件下载及总结网友遇到的各种hosts问题解决方法及配置详解

相关阅读:你一直使用的能FQ的hosts文件原理是什么?怎么配置?|我来科普下

出处 酷 壳 – CoolShell

作者:陈浩

相关BLOG:SUN’S BLOG - 专注互联网知识,分享互联网精神!去看看:www.whosmall.com

时间: 2024-10-15 17:50:53

从一些简单代码实例彻底理解面向对象编程思想|OOP本质是什么?的相关文章

面向对象编程思想(OOP)

本文我将从面向对象编程思想是如何解决软件开发中各种疑难问题的角度,来讲述我们面向对象编程思想的理解,梳理面向对象四大基本特性.七大设计原则和23种设计模式之间的关系. 软件开发中疑难问题: 软件复杂庞大 很多软件进入维护阶段 需求的不断变更 软件开发中存在很多其他的问题,上面只是从程序开发和设计的角度看到的部分问题.需求解决上面软件开发中的问题,就要求我们编写(设计)的软件具有很好的可读性.可维护性和可扩展性.我们需要保证代码具有高内聚低耦合. 下面将简单介绍面向对象的一些基本特性.设计原则,以

深入浅出理解面向对象编程思想

C#是一门面向对象的编程语言.关于面向对象编程,首先是,面向对象编程英文 Object-Oriented Programming 简称 OOP.通俗来说,就是 针对对象编程的意思,面向对象中的对象,指一切皆是对象.面向对象——是把构成问题的事务分成各个对象,利用对象之间的关系来解决问题,面向对象因为把事务分成各个对象,所以更容易实现对象的封装,对象的复用.这也就是面向对象的几种特征(封装.继承.多态)这个后面再说. 为了更明白一点,举个例子: 比如要解决去某金融公司上班这个问题,采用面向对象实现

面向对象编程思想 - 月亮晶石的日志 - 网易博客

面向对象是一种新兴的程序设计方法,或者说它是一种新的程序设计范型,其基本思想是使用对象,类,继承,封装,消息等基本概念来进行程序设计. 它是从现实世界中客观存在的事物(即对象)出发来构造软件系统,并在系统构造中尽可能运用人类的自然思维方式,强调直接以问题域(现实世界)中的事物为中心来思考问题,认识问题,并根据这些事物的本质特点,把它们抽象地表示为系统中的对象,作为系统的基本构成单位(而不是用一些与现实世界中的事物相关比较远,并且没有对应关系的其它概念来构造系统).这可以使系统直接地映射问题域,保

什么是面向对象编程(OOP)?

Java 程序员第一个要了解的基础概念就是:什么是面向对象编程(OOP)? 玩过 DOTA2 (一款推塔杀人的游戏)吗?里面有个齐天大圣的角色,欧洲战队玩的很溜,国内战队却不怎么会玩,自家人不会玩自家的神话英雄,实在有点悲哀. 我们用 Java 定义一个孙悟空的类吧: public class SunWukong { private Integer healthPoint;// 生命值 private Integer magicPoint;// 魔法值 /** * 棒击大地 */ private

面向对象编程思想的哲学起源(转载)

http://www.xuebuyuan.com/566309.html 本来想象着写一整篇「面向对象编程思想的哲学起源」这样的题目,笔走纸上,方才发现这样的题目足够出本书,知识不够,写不动.但心里还是想写点自己的所思所想. 全篇就拿JAVA来举例了.众所周知,面向对象的四大基本要素:抽象(Abstract).封装(Encapsulation).继承(Inheritance).多态(Polymorphism). 很多人坚持<逻辑学>是唯物哲学的基础,不懂,姑且不论.哲学就是对自然学科的抽象,看

面向对象编程思想(OOP)

本文我将从面向对象编程思想是如何解决软件开发中各种疑难问题的角度,来讲述我们面向对象编程思想的理解,梳理面向对象四大基本特性.七大设计原则和23种设计模式之间的关系. 软件开发中疑难问题: 软件复杂庞大 很多软件进入维护阶段 需求的不断变更 软件开发中存在很多其他的问题,上面只是从程序开发和设计的角度看到的部分问题.需求解决上面软件开发中的问题,就要求我们编写(设计)的软件具有很好的可读性.可维护性和可扩展性.我们需要保证代码具有高内聚低耦合. 下面将简单介绍面向对象的一些基本特性.设计原则,以

面向对象编程思想(前传)--你必须知道的javascript(转载)

原文地址:http://www.cnblogs.com/zhaopei/p/6623460.html阅读目录 什么是鸭子类型 javascript的面向对象 封装 继承 多态 原型 this指向 call apply band js中的闭包 什么是高阶函数 在写面向对象编程思想-设计模式中的js部分的时候发现很多基础知识不了解的话,是很难真正理解和读懂js面向对象的代码.为此,在这里先快速补上.然后继续我们的面向对象编程思想-设计模式. 什么是鸭子类型 javascript是一门典型的动态类型语

[Javascript] 面向对象编程思想

1.创建对象 1.1 new 用new进行创建对象: var user = new Object(); user.age = 12;//同时为对象添加属性 user.name = 'ajun'; 1.2{} 用{}创建对象,如: var user = { 'name':'ajun, 'age':12 } 这里同时候为user添加了两个属性分别为:name,age 在以上代码稍加改造,你还可以为一个对象添加一个方法,如: var user = { 'name':'ajun', 'age':12 '

第三章面向对象编程思想

""" 编码规范: 类名首字母应以大写字母开头 类的成员/属性: 成员属性 实例化对象的属性: self.name=name 可以被访问,也可以在类的外部被修改 私有属性 实例化对象的私有属性: self.__age=age 属性名前加两下划线 外部无法被访问, 也不能被修改,只能内部访问和修改 想要在外部访问只能自定义一个方法了 强制访问 私有属性: p._People__age 对象名._类名__私有属性 公共属性: 类的属性,也叫静态属性,他是在类的内部定义的 clas