zoukankan      html  css  js  c++  java
  • 面向对象

    http://bbs.csdn.net/topics/220013605

    【18楼】

    打个比方,让你编一个计算正方形的程序,一般的思路是: 
    定义3个变量,a=长,b=宽,c=a*b 
    而面向对象的思路: 
    先创建一个长方形的类,在类里定义两个属性分别为长、宽,再定义一个面积方法 
    然后实例化这个类

    【19楼】

    你这样的例子没用!比如说我做一个网站,而这个网站里有个计算正方形面积的功能,我完全可以像你说的用一个Square类来表示正方形,长、宽是属性,计算面积是方法,然后我从保存“形状”的数据表中取出一个正方形,然后通过Square类计算它的面积,然后返回到网站的用户界面上显示面积的结果。
    这跟我说的网站设计的那个流程有什么区别?从宏观角度来说,也是数据的提交和回送。只不过是多了一个用“类”来表示对象的方式,任何初学者完全都可以用你这样的思路来设计,但是照样被人指成是“面向过程”。

    【24楼】

    你这样想还是面向过程的想法,面向对象说穿了就像 wanghui0380 说的那样就是封装变化和类重用。
    举个例子来说吧,你要在网站增加个log功能,如果你是已面向过程的想法可能就是这样

    public class Log
    {
       public void Write(string loginfo)
       {
         //具体的实现,假如说是写入到数据库中
       }
    }
     

    然后你就在各个需要用到log功能的地方增加
    Log log = new Log();
    log.Write("信息1");
    你看看,这段代码中有class吧,也解决了实际的问题了,但你这就是面向对象了吗?
    这时候项目要求变化了,要将原来要存入数据库中改为存入文件中,你就会发现需要修改代码了,不过简单!将Log中的Write修改一下就可以了。
    接着项目需求又变了,Log有的地方要存到数据库中,有的地方要存入文件中,又要改代码了,怎么改呢,像这样改?

    public class Log
    {
       public void WriteDataBase(string loginfo)
       {
         //具体的实现,假如说是写入到数据库中
       }
       public void WriteFile(string loginfo)
       {
       //具体的实现,假如说是写入文件中
       }
    }

    你会发现噩梦来了,你需要修改散落在项目中成千上万个调用的代码,即使你修改好了,那以后呢?需求又变化了呢?
    你会想为什么会出现这样的问题,我不是也使用了对象了吗?甚至我的项目也使用到了分层了呀?难道不是面向对象吗?
    没错,你是使用了这些时髦的技术,什么反射啊,分层啊,封装、继承、多态你都很熟悉,但你的思路仍然处在面向过程之中,你只是以面向过程的思路来解决问题而已

    【139楼】

    对象分析一般从一个具体用例描述开始
    比如:
    收银员根据顾客选购的商品收费

    这个就是一个具体用例。
    首先分析名词:
    收银员  顾客  商品
    然后是动作:
    计算费用并收费

    然后是限定

    操作人员--收银员,管理人员,定价人员,会计,仓管人员
    商品-普通商品,折扣商品
    顾客-普通客户,普通vip客户,大集团客户

    接着是控制:
    商品价格控制
    顾客类型控制

    最后是关系
     商品价格由具有该权限的人员管理
     费用由顾客类型决定

    于是最终设计可能就为
     操作人员类(这里可能是一个工厂类)
    顾客类(这里也可设计成工厂类)
    商品类(一个商品可能根据顾客不同而有不同的价格,所以这里可能是个装饰类
    费用计算类(限定接口,只允许接收顾客和商品列表两参数,以保证最终调用者始终只有一种调用方式)

    我这里只是一个简单的分析,我为了描述上的简单把实体类和控制类合并了,不过如果是了解设计模式的人估计是看的明白的。

    【194楼】

     面向对象编程:先把一个问题抽象化出一个类来(类的属性--即数据成员--和方法---即成员函数);面向对象的模块是“类”。面向对象的编程是以类的设计为基础的--即把待解决的问题抽象出一个类出来。

    面向过程编程:把解决一个问题当作一个主函数--对应main problem(主问题),把主问题分解成几个子问题,然后把要实现的一些细节问题(即子问题)当作主函数中调用的一些函数;面向过程的模块是“函数”。面向过程程序设计通常是采用自顶向下设计方法设计的---即将待解决的问题分成几个子问题。

    【306楼】

    培养OO思想其实很简单,当你遇到一个需求时,先把这个需求拿出来,单独思考,想他可能有什么属性,有什么方法,是否有功能类似的兄弟姐妹,之后单独实现,并且用单元测试来测试。 最后在回到需求点调用。
    借用24楼兄弟的例子,如果你现在写UI,需要记录log,你可能很自然的想到
    class Logger
    {
        void Log(string message){}
    }
    然后你回到UI,调用Logger.Log("用户登录成功了"),这就是典型的面向过程的思想。你甚至可能会写个Logger的接口,但你的思想还是面向过程。

    而如果你想我的项目需要一个Log功能,他可能需要记录exception,记录Event,记录自定义的Message,他可能记录到database,记录到文件,甚至记录到串口,或许将来会记录到不可预见性的地方,那么你需要提供配置文件,Logger工厂和继承的子Logger来扩展。 这样,一个丰富的,有血有肉的Logger对象浮出水面。
    接下来你可能考虑如何调用这个Logger,直接在UI调用可能是不明智的,他违背了MVC原则,那么你可能需要一个SystemEvents对象,专门负责抛出各种各样的Events,或者打入MessageQueue。好了,既然我们有了SystemEvents对象,我们还需要一个监视对象来监视SystemEvents的变化,并最终记录到Logger中。
    OK,小功告成,我们有了一套互相协调工作的对象,大家互相配合完成一些工作,这时候你可以完成你的代码了,你的代码可以写的非常丑陋,你可以没有继承,没有多态,但是你的思想已经是OO思想了。

    很多朋友可能误解了,以为继承,多态就是OO。其实OO在前,技术在后。先辈们有了OO的思想,然后发明了继承,多态等技术来更好的实现这种OO思想。记住,OO是思想,是思路。

    【413楼】反射的应用

    编程都是面向过程的,而程序的设计才是面向对象。为什么要有架构师?架构师可能什么语言都不会,也可能什么语言都知道一点,你要他写个hellworld他还不一定写得好,但他的职责就是设计,就像楼上说的搭房子一样,架构师就像画图纸的一样,一栋高楼大厦,不同的人住在里面会有不同的需求,那就面临改建的问题,难道为了一家住户把整个楼拆了?当然不可能,所以在设计的时候就要考虑将来可能会面临什么样的改建需求,于是主梁应该有几根、地基应该打多深、改建时哪些地方会造成重心变化都要考虑。

    继承、封闭、多态的确都是面向对象编程中提到的东西,这些是面向对象的核心,但个人认为:这些核心的核心都是为了一个词——重用。就是说为了减少编程过程中重复写大量相同的代码而提出的一些办法。

    就拿前面举过的计算矩形面积的方法来说,这个方法只能计算矩形的面积吗?显然不是,假设方法为S(x,y),方法返回的是x、y的乘积,那如果这样调用呢——S(S(x,y),z),显然可以返回一个体积(可能是立方体也可能是圆柱体甚至是锥体),所以如果这个类里只有这个方法的话,那此类可在需要返回任何计算过程为两个数的乘积的程序中调用。

    再拿这个类来举例,如果一个程序是计算面积的,第一天只说要计算矩形面积,于是你在程序中写(假设那个类名为A)
    A a = new A();
    double s = a.S(x,y);
    第二天需求变了,添加计算x的y次幂的功能。于是你可能会在类A中添加一个方法B(x,y)返回x的y次幂,也可能你想到类的单一职责,再写一个类B,添加方法S(x,y)返回x的y次幂,但不管哪种你都得在主程序中再修改成这样:
    double s = 0;
    if(要求==计算矩形面积){
      A a = new A();
      s = a.S(x,y);
    }else if(要求==计算x的y次幂){
      A a = new A();
      s = a.B(x,y);(或者 B b = new B();s = b.S(x,y);)
    }
    新的需求越来越多,但无论需求怎么变都是让你对两个参数作不同的运算。但你要改的还是会越来越多,主程序要添加的代码也越来越多。其实仔细比较判断中的两段,就会发现代码基本是一样的,只是调用的类的方法(或类)不同而已,方法的签名都一样!那怎样使重复代码减少呢?
    利用反射即可漂亮的解决这个问题,写一个接口ITest,里面有个方法double T(x,y);于是在主程序中你只需写这样一段:
    String className = "";
    /*不同需求就对className赋不同的值,值为对应功能的类的名字,最好把对应关系写在XML文件中,比如这样:
    <GetName demand="计算矩形面积" ClassName="A">(这个只是图简单举的例子,具体怎样对应看个人爱好,呵呵)
    这样以后添加新类的时候只需修改XML文件即可,而程序中只需用一个方法根据传入的需求参数返回对应的类名*/
    ITest t = (ITest)Activator.CreateInstance(Type.GetType(className));
    double s = t.T(x,y);
    这样完成后,新需求来了,加个类,改一下XML文件,其他都不用动,而原来的类还能用在其他地方。这样很大程序减少了冗余代码,也一定程序达到了重用的目的。这应该算是面向对象的一个小例子吧。

    【435楼】

    你可以把对象看作现实中应该独立存在的某种实体或者观念,多个对象并行地运行,就像物理中的“原子”或者社会中的“组织”,都是从看似有生命周期的个体的角度去考虑问题。

    肯定不会使用简单的计算机值类型去表达对象,而从用户创立的计算机本没有的类型去表达(封装)。

    考虑现实社会中这些个体如何独立存在、相互协作、发生变化,不要使用计算机领域的概念去分析需求。

    面向对象分析,不但可以给计算机使用,更可以给人使用,作为反映行为科学的工具。

    面向对象设计的代码要尽量与面向对象分析风格保持一致,才会让你的代码容易阅读、优化和扩展。

    面向对象程序的优化往往是在实际架构上优化,而不是死抠几个语句的CPU运行时间去优化,结构优化往往带来巨大的改变,就好像一个人突然对某个行业的认识入门了,他的结构就改变了。

    他的结构就改变了    -->   他的逻辑表达的结构就改变了  ,而不是靠在行业无关的方面去下功夫。学计算机语言不一定能够学会面向对象方法。

  • 相关阅读:
    [每日一讲] Python系列:浅拷贝与深拷贝
    [每日一讲] Python系列:变量、内存管理与传递
    [每日一讲] Python系列:字典
    [每日一讲] Python系列:列表与元组
    [已开源/文章教程]独立开发 一个社交 APP 的源码/架构分享 (已上架)
    从选择到上传,可能是最贴心的高仿朋友圈编辑了
    完整的社交app源码android+laravel
    基于Laravel+Swoole开发智能家居后端
    APP架子迁移指南(三)
    Laravel如何优雅的使用Swoole
  • 原文地址:https://www.cnblogs.com/chucklu/p/4499468.html
Copyright © 2011-2022 走看看