• 设计模式(二):面向对象及其特性分析


    面向对象

    根据大纲,首先我们来学习一种代码设计与编写的风格,即面向对象。

    面向对象编程和面向对象编程语言

    • 面向对象编程是一种编程范式,通俗来说,就是将 代码的组织单元改成类和对象,并将 封装、继承、抽象、多态 作为代码设计和编写的基石。
    • 面向对象编程语言代表了能简易实现面向对象编程范式的语言,其如果能够用现成的语法机制来实现范式,就是面向对象编程语言。


    从上述的定义中,我们可以看出,面向对象编程不一定非要用面向对象编程语言来实现,同时,当我们使用面向对象编程语言来编写代码时,可能写出来的却反而是面向过程的代码。

    面向对象分析和面向对象设计分别是什么

    既然面向对象编程重点是类和对象的实现,那么针对分析和设计其实就是类和对象该如何设计。


    分析讲的就是做什么,而设计讲的就是怎么做。通过这两个阶段产出类的设计,包括该拆出什么类、每个类有哪些属性和方法、类和类之间如何交互等。

    封装

    定义:封装的定义是隐藏类中的信息。通过暴露有限的接口,来保护一些数据,只提供一些开放的接口来完成指定的业务。


    实现方式:在 Java 代码的实现通过 public、private 等关键词来实现。通过这些关键字来确定访问权限,从而隐藏对应字段。


    意义:

    • 安全、可控,因为我们指定了哪些属性是可暴露给外部,哪些是只能按照指定方式来修改的,因此更加安全可控;
    • 好理解,因为在代码的实现里封装了多数细节,只暴露一些开放的接口,因此不需要调用者太了解全部就可以使用了。

    抽象

    定义:抽象的定义和封装类似,封装封的是类内的属性字段,抽象抽的是行为的具体实现方式。


    实现方式:在 Java 代码里通过 interface 或 abstract class 来实现。但该特性并不是一个面向对象特有特性,只要语言里有函数的概念,就可以通过多种方式来实现抽象特性。


    意义:

    • 因为只暴露方法的定义,因此对使用方来说,不需要关注具体的实现,只面向定义使用即可,内部如何实现以及后续如何更改,只要保证定义不变,使用方就不需要更改;


    为了实现上述意义,因此在设计方法定义时,尽量保证方法的定义和具体实现无关,来保证面对需求的修改时可以从容修改。

    继承

    定义:继承好理解了,其实现的是 is-a 的语义,举个例子来说,设计父类是哺乳动物的话,那么子类就可以是猫、狗、人等,这些子类都属于父类的一种。


    实现方式:在 Java 代码里继承是通过 extend 关键字来实现的。


    意义:继承最重要的就是解决代码复用的问题,即子类复用父类的属性和方法,避免重复的代码编写多次。




    带来的问题:

    • 多继承问题,在 Java 里是没有多继承的,因为多继承会出现菱形问题,导致语义不清,因此官方不允许使用多继承,即一个子类只可以继承一个父类。
    • 继承层次过深,如果继承的层级结构比较复杂,那么在想要知道一个类中的某个具体行为实现,可能就需要看很多层级,从而影响代码的可读性和可维护性。


    image.png

    在 A 中定义了一个方法 test(),类 B 和 类 C 都继承了A,并对 test() 进行了重写,此时有个类 D 同时继承类 B 和类 C,那么类 D 在调用 test() 方法的时候,该调用哪一个呢?这就是菱形问题带来的语义混乱。


    组合和继承:
    针对上述所述的问题,因此推荐使用组合的形式来代替继承,具体的实现方式的话,在后面的文章中再详细描述。

    多态

    定义:简单来说,就是父类指针可以指向子类对象,从而在代码实际运行过程中,根据具体是哪一个对象,来决定调用哪个对象的方法。


    实现方式:文字不好解释,直接代码来解释。

    // 首先定义一个接口
    public interface ImageStore {
        void sayHello();
    }
    
    // 定义一个类来实现接口,并重写其中的方法
    public class AliyunImageStore implements ImageStore {
        @Override
        public void sayHello() {
            System.out.println("AliyunImageStore say Hello");
        }
    }
    
    // 再定义一个类来实现接口,并重写其中的方法
    public class TencentImageStore implements ImageStore {
        @Override
        public void sayHello() {
            System.out.println("TencentImageStore say Hello");
        }
    }
    
    // 用接口来指向具体子类,从而调用子类的方法
    public class Demo {
        public static void main(String[] args) {
            ImageStore aliyun = new AliyunImageStore();
            aliyun.sayHello();
    
            ImageStore tencent = new TencentImageStore();
            tencent.sayHello();
        }
    }
    

    image.png

    意义:
    提高代码的可拓展性,通过父类指针来操作数据,保证在代码中实现一个逻辑,可以复用多次。

    公众号截图




    文章在公众号「iceWang」第一手更新,有兴趣的朋友可以关注公众号,第一时间看到笔者分享的各项知识点,谢谢!笔芯!

  • 相关阅读:
    漂亮的代码5:数组与字符一样的操作
    漂亮的代码4:缓存器的妙用
    漂亮的代码3:flatten 一个数组
    漂亮的代码2:遍历文件夹目录,使用promise
    漂亮的代码1:计算器
    nodejs 代码设计模式1:同步函数变异步
    [翻译]现代java开发指南 第二部分
    Httpclient远程调用WebService示例
    Java代码使用正则验证和常用工具方法
    简单将集合的内容转为字符串
  • 原文地址:https://www.cnblogs.com/JRookie/p/13856290.html
Copyright © 2020-2023  润新知