C++——OOP面向对象理解
从Rob Pike 的 Google+上的一个推看到了一篇叫《Understanding Object Oriented Programming》的文章,我先把这篇文章简述一下,然后再说说老牌黑客Rob Pike的评论。
先看这篇教程是怎么来讲述OOP的。它先给了下面这个问题,这个问题需要输出一段关于操作系统的文字:假设Unix很不错,Windows很差。
这个把下面这段代码描述成是Hacker Solution。(这帮人觉得下面这叫黑客?我估计这帮人真是没看过C语言的代码)
	public class PrintOS
{
    public static void main(finalString[] 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.") ;
        }
        elseif(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.") ;
        }
    }
}
然后开始用面向对象的编程方式一步一步地进化这个代码。
先是以过程化的思路来重构之。
过程化的方案
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(finalString osName)
    {
        if(osName.equals("SunOS") || osName.equals("Linux"))
        {
            returnunixBox() ;
        }
        elseif(osName.equals("Windows NT") ||osName.equals("Windows 95"))
        {
            returnwindowsBox() ;
        }
        else
        {
            returndefaultBox() ;
        }
    }
    public static void main(finalString[] args)
    {
        System.out.println(getTheString(System.getProperty("os.name"))) ;
    }
}
然后是一个幼稚的面向对象的思路。
幼稚的面向对象编程
PrintOS.java
publicclassPrintOS
{
    publicstaticvoidmain(finalString[] args)
    {
        System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
    }
}
OSDiscriminator.java
	publicclassOSDiscriminator// Factory Pattern
{
    privatestaticBoxSpecifier theBoxSpecifier =null;
    publicstaticBoxSpecifier getBoxSpecifier()
    {
        if(theBoxSpecifier ==null)
        {
            String osName = System.getProperty("os.name") ;
            if(osName.equals("SunOS") || osName.equals("Linux"))
            {
                theBoxSpecifier =newUNIXBox() ;
            }
            elseif(osName.equals("Windows NT") || osName.equals("Windows 95"))
            {
                theBoxSpecifier =newWindowsBox() ;
            }
            else
            {
                theBoxSpecifier =newDefaultBox () ;
            }
        }
        returntheBoxSpecifier ;
    }
}
BoxSpecifier.java
	publicinterfaceBoxSpecifier
{
    String getStatement() ;
}
DefaultBox.java
	publicclassDefaultBoximplementsBoxSpecifier
{
    publicString getStatement()
    {
        return"This is not a box.";
    }
}
UNIXBox.java
	publicclassUNIXBoximplementsBoxSpecifier
{
    publicString getStatement()
    {
        return"This is a UNIX box and therefore good.";
    }
}
WindowsBox.java
	publicclassWindowsBoximplementsBoxSpecifier
{
    publicString getStatement()
    {
        return"This is a Windows box and therefore bad.";
    }
}
他们觉得上面这段代码没有消除if语句,他们说这叫代码的“logic bottleneck”(逻辑瓶颈),因为如果你要增加一个操作系统的判断的话,你不但要加个类,还要改那段if-else的语句。
所以,他们整出一个叫Sophisticated的面向对象的解决方案。
OO大师的方案
注意其中的Design Pattern
PrintOS.java
	publicclassPrintOS
{
    publicstaticvoidmain(finalString[] args)
    {
        System.out.println(OSDiscriminator.getBoxSpecifier().getStatement()) ;
    }
}
OSDiscriminator.java
	publicclassOSDiscriminator// Factory Pattern
{
    privatestaticjava.util.HashMap storage =newjava.util.HashMap() ;
publicstaticBoxSpecifier getBoxSpecifier()
    {
        BoxSpecifier value = (BoxSpecifier)storage.get(System.getProperty("os.name")) ;
        if(value ==null)
            returnDefaultBox.value ;
        returnvalue ;
    }
    publicstaticvoidregister(finalString key,finalBoxSpecifier value)
    {
        storage.put(key, value) ;// Should guard against null keys, actually.
    }
    static
    {
        WindowsBox.register() ;
        UNIXBox.register() ;
        MacBox.register() ;
    }
}
BoxSpecifier.java
	publicinterfaceBoxSpecifier
{
    String getStatement() ;
}
DefaultBox.java
	publicclassDefaultBoximplementsBoxSpecifier// Singleton Pattern
{
    publicstaticfinalDefaultBox value =newDefaultBox () ;
    privateDefaultBox() { }
    publicString getStatement()
    {
        return"This is not a box.";
    }
}
UNIXBox.java
	publicclassUNIXBoximplementsBoxSpecifier// Singleton Pattern
{
    publicstaticfinalUNIXBox value =newUNIXBox() ;
    privateUNIXBox() { }
    public  String getStatement()
    {
        return"This is a UNIX box and therefore good.";
    }
    publicstaticfinalvoidregister()
    {
        OSDiscriminator.register("SunOS", value) ;
        OSDiscriminator.register("Linux", value) ;
    }
}
WindowsBox.java
	publicclassWindowsBoximplementsBoxSpecifier // Singleton Pattern
{
    public  static final WindowsBox value =new WindowsBox() ;
    privateWindowsBox() { }
    publicString getStatement()
    {
        return"This is a Windows box and therefore bad.";
    }
    publicstaticfinalvoidregister()
    {
        OSDiscriminator.register("Windows NT", value) ;
        OSDiscriminator.register("Windows 95", value) ;
    }
}
MacBox.java
	publicclassMacBoximplementsBoxSpecifier// Singleton Pattern
{
    publicstaticfinalMacBox value =newMacBox() ;
    privateMacBox() { }
    public  String getStatement()
    {
        return"This is a Macintosh box and therefore far superior.";
    }
    publicstaticfinalvoidregister()
    {
        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的设计准则。
(全文完)
C++——OOP面向对象理解的更多相关文章
- c#基础-oop(面向对象理解)
		OOP-面向对象 封装,继承多态 一个桌子,用面向对象来描述一下它这个桌子项目 定义桌子类 对象:桌子 桌子的属性:名字,材质,体积 桌子的方法;放东西(方法) 现在桌子要放书,放花瓶,放文件(这里就 ... 
- js面向对象理解
		js面向对象理解 ECMAScript 有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是, ... 
- OOP面向对象     三大特征 继承封装多态
		OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ... 
- OOP面向对象三大特点
		OOP面向对象三大特点 (一)封装:将现实中一个事物的属性和功能集中定义在一个对象中.(创建对象) 创建对象的3种方式: 1.直接量方式:(创建一个单独的对象) var obj={ 属性名:值, ... 
- 我个人对OOP的理解
		OOP面向对象的思维:pay1:封装 A.避免使用非法数据赋值 B.保证数据的完整性 C.避免类内部发生修改的时候,导致整个程序的修改 pay2:继承 A.继承模拟了现实世界的关系,OOP中强调一切皆 ... 
- OOP 面向对象   七大原则 (二)
		OOP 面向对象 七大原则 (二) 上一篇写到了前四个原则,这一篇继续~~ 接口隔离:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 又是一句大白话~就是说接口尽量 ... 
- OOP 面向对象   七大原则 (一)
		OOP 面向对象 七大原则 (一) 大家众所周知,面向对象有三大特征继承封装多态的同时,还具有这七大原则,三大特征上一篇已经详细说明,这一篇就为大家详解一下七大原则: 单一职责原则,开闭原则,里氏 ... 
- 用C实现OOP面向对象编程(1)
		如摘要所说,C语言不支持OOP(面向对象的编程).并这不意味着我们就不能对C进行面向对象的开发,只是过程要复杂许多.原来以C++的许多工作,在C语言中需我们手动去完成. 博主将与大家一起研究一下如下用 ... 
- OOP面向对象程序设计原则
		OOP面向对象程序设计原则 开闭原则(Open Close Principle) 对扩展开放,对修改关闭 里氏代换原则(Liskov Substitution Principle) 继承必须确保超累所 ... 
随机推荐
- PHP学习课程和培训方向学习路线分享
			php语言的优越性,集结了很多的开发爱好者,无论行业前景和个人发展来说,php正飞速的发展,php在不断兼容着类似closures和命名空间 等技术,同时兼顾性能和当下流行的框架.版本是7之后,一直在 ... 
- Python基础02
			6.变量定义的规则: # 变量,只能由 字母 数字 下划线 特例:不能用数字开头 Python关键字,也不能使用 'and', 'as', 'assert', 'break', 'class', 'c ... 
- error:control reaches end of non-void function [-Werror=return-type]
			在做LeetCode上的题目时,出现了这个错误, 原代码如下: class Solution { public: vector<int> twoSum(vector<int>& ... 
- Kuernetes-设计架构(二)
			Kubernetes设计架构 Kubernetes集群包含有节点代理kubelet和Master组件(APIs,scheduler.etc),一切都基于分布式的存储系统.Kubernetes架构图: ... 
- (数据科学学习手札14)Mean-Shift聚类法简单介绍及Python实现
			不管之前介绍的K-means还是K-medoids聚类,都得事先确定聚类簇的个数,而且肘部法则也并不是万能的,总会遇到难以抉择的情况,而本篇将要介绍的Mean-Shift聚类法就可以自动确定k的个数, ... 
- PHP.42-TP框架商城应用实例-后台17-商品属性3-商品分类的修改与删除
			商品分类的修改 1.改表单Goods/edit.html,加下拉框 2.因为商品属性修改涉及商品属性表goods_attr{id,attr_value,attr_id,goods_id}与属性表att ... 
- Sphinx与coreseek
			Sphinx : 高性能SQL全文检索引擎 分类 编程技术 Sphinx是一款基于SQL的高性能全文检索引擎,Sphinx的性能在众多全文检索引擎中也是数一数二的,利用Sphinx,我们可以完成比数据 ... 
- How to find your web part
			When we deploy a web part, we can find it on any pages through the follow steps: Firstly, ... 
- 2018春季校园招聘笔经面经合集:Java开发岗
			2018春季校园招聘笔经面经合集:Java开发岗 以下为精选面经: 美团外卖配送部后台开发面经 nowcoder.com/discuss/76 春招总结,干货满满 nowcoder.com/discu ... 
- AutoMapper.RegExtension 介绍
			AutoMapper.RegExtension 为一个特小特小特小的用来根据约定自动调用AutoMapper中的方法配置映射的扩展库.你可以引入该库也可以将源码中核心部分的代码文件夹整个拷贝至项目中. ... 
