设计模式前篇之:一起过一下面向对象的概念

面向对象编程,好像从来都是最熟悉的陌生人,相信大家都看过难记难懂的概念。面向对象的设计模式存在大量的类结构,体现面向对象的四个特征和遵循面向对象的六个原则,认识它们才能更好理解设计模式。今天就写一写它们,也相对于给自己做笔记。

面向对象与面向过程:

还是觉得有必要再过一下面向对象和面向过程的基本概念,这是人类思维进步的一种体现。

面向对象编程:
面向对象编程(Object Oriented Programming,OOP)是一种思想,它将所有预处理的问题抽象为对象,以解决对象一些实际问题。本质是对现实世界的对象进行建模操作。

简述一下,面向对象编程把要解决的问题按照现实世界的规律分解成一个一个对象去处理,按功能划分某个事物自身的属性与行为。

面向过程编程:
面向过程编程(Procedure Oriented Programming,POP)是一种编程思想。它将所有预处理的问题看作一系列需要完成的任务,函数则用于完成这些任务,解决问题的焦点集中于函数。

总而言之,面向过程编程把需要解决的问题按照步骤去处理,然后用函数一步一步实现,使用的时候一个一个依次调用。

举个例子:
相信大家接触编程都是以四则运算起步的,下面就用加减乘数的算法区别一下面向对象与面向过程。

需要解决的问题:用四则运算计算两个数(本例子暂且忽略精度与非零问题)。

面向过程编程实现很简单,把加减乘数的功能按照函数划分,然后按照顺序一步一步实现。如下:

public class Program {

    public static void main(String[] args) {
        int num1 = 4;
        int num2 = 2;

        //加法运算
        System.out.println(add(num1, num2));
        //减法运算
        System.out.println(subtract(num1,num2));
        //乘法运算
        System.out.println(multiply(num1,num2));
        //除法运算
        System.out.println(divide(num1,num2));
    }

    public static int add(int a, int b) {
        return a + b;
    }

    public static int subtract(int a, int b) {
        return a - b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }

    public static int divide(int a, int b) {
        return a / b;
    }

}

再看看面向对象的实现,加减乘数是一种运算的行为,是一组相似的事物。因此,把四则运算的功能抽象成一个运算类,而这个类的功能就是只做四则运算了。代码如下:

public class Operation {

    public static int add(int a, int b) {
        return a + b;
    }

    public static int subtract(int a, int b) {
        return a - b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }

    public static int divide(int a, int b) {
        return a / b;
    }

}

再改改Program类的方法吧:

public class Program2 {

    public static void main(String[] args) {
        int num1 = 4;
        int num2 = 2;

        //加法运算
        System.out.println(Operation.add(num1,num2));
        //减法运算
        System.out.println(Operation.subtract(num1,num2));
        //乘法运算
        System.out.println(Operation.multiply(num1,num2));
        //除法运算
        System.out.println(Operation.divide(num1,num2));
    }

}

知道区别后就差不多了,优缺点不归纳了,显而易见。下面进入正题。

面向对象四个特征:
是这四个特征:抽象、封装、继承、多态,下面一个个简单过一遍。

抽象:
用现实世界的规律,把一类相似事物的属性和行为提取出来,构成一个类的模板,这种研究问题的方法称为抽象。

就如刚才的运算类,把具有相似行为(加减乘数功能)提取出来,构成了一个类。

封装:
指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,并尽可能隐藏对象的内部实现细节,这个过程称为封装。

封装的重点在于访问属性(public、private、protected)。例如我们使用计算机时,只知道用鼠标或用键盘就可以对电脑进行操作实现一些功能,无需知道计算机内部的工作原理。因此,键盘和鼠标对我们来说是public的,计算机内部的功能是private的。

继承:
当多个类具有相同的属性与行为时,可以这些类抽象出一个父类。子类继承父类后具有父类的属性与行为的同时,能够扩展新的功能。子类与父类的关系称之为继承。

举个现实例子。鸟类动物都有羽毛和翅膀(属性),通过下蛋去繁殖后代(行为)。大雁是一种鸟类,它也有羽毛和翅膀,也能够下蛋(复用父类的属性和方法),并且能够飞(扩展新功能)。

多态:
当同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。

以Java语言为例,实现多态有三个必要条件:抽象类和接口、重写、向上转型。代码举例:

条件一:接口。首先定义一个Fly接口先:

public interface Fly {
    void flyaway();
}

条件二:重写接口方法。下面有一只企鹅和一只大雁:

public class Penguin implements Fly {
    @Override
    public void flyaway() {
        System.out.println("企鹅不会飞!");
    }
}
public class WildGoose implements Fly{
    @Override
    public void flyaway() {
        System.out.println("飞得很高!");
    }
}

条件三:向上转型,父类引用指向子类对象。直接看主函数了:

public static void main(String[] args) {
    Fly fly = new WildGoose();
    fly.flyaway();//输出飞得很高!
        
    fly = new Penguin();
    fly.flyaway(); //输出企鹅不会飞!
}

简单过一遍类的特征,其中包含的接口、重写、向上转型等概念就不展开写了,大家可以参考书或其它文章哈。

面向对象六个原则:
用个人认为最简单理解的语言整理一下。分别是这六个:单一职责原则、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特原则。

单一职责原则
单一职责原则(Single Responsibility Principle,SRP)定义了就一个类而言,应该仅有一个引起它变化的原因。

很简单,意思就是设计类时实现的功能要单一,尽可能只做一件事情,不能把很多功能都写到一个类里面去。

开闭原则
开闭原则(Open Close Principle,OCP)定义了软件中的对象(类、模块、函数等)应该对于扩展是开放的,对于修改是封闭的。

对扩展开放,对修改封闭,意思就是当需求改变时,应该尽量去扩展原来的代码,而不是去修改原来的代码,因为这样可能会引起更多的问题。

里氏替换原则
里氏替换原则(Liskov Substitution Principle,LSP)定义了引用基类的地方必须能够透明地使用其子类。

只要父类出现的地方子类就可以出现,这个原则依赖于继承和多态。子类可以去扩展父类的功能,但是不能改变父类原有的功能,以免破坏整个继承体系。

依赖倒置原则
依赖倒置原则(Dependence Inversion Principle,DIP)定义为高层模块不应该依赖于底层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。可以概括为面向接口编程。

该原则可以理解成在声明成员变量、方法的参数或返回类型时,尽量使用抽象类型(抽象类或接口),而不用具体类型。

接口隔离原则
接口隔离原则(Interface Segregation Principle,ISP)定义是客户端不应该依赖它不需要的接口。另一种定义是:类间的依赖关系应该建立在最小的接口上。

在Java中实现接口就会实现接口中的所有方法。简单来说写接口不能写太臃肿,要拆分,当其它类也用到相同的接口时就能避免实现空方法。

迪米特原则
迪米特原则(Law Of Demeter,LOD),也称最少知识原则。定义一个对象应该对其他对象有最少的了解。

意思是只与朋友通讯(关联度很高的类)。每个类都会必然用到其它类的属性和方法,这称为耦合。设计类的时候要把功能拆分,尽可能使用一个第三者的朋友来进行两者间的通讯。

总结:
四大特征和六大原则明白了,面向对象其实就这么回事。这篇文章只是简单过一下,每个概念还有很多细节没有提到,主要为设计模式铺垫一下,过一遍基础。

要特别说一下,遵循原则都是为了应对千变万化的需求,尽可能对自己的影响降到最少,这些原则都是前人靠经验总结出来的东西,并不是一个结论。所以说不是每一个类都必须得遵循六大原则,反而会造成过度设计。

推荐阅读

基础篇:
设计模式前篇之——UML类图必会知识点
设计模式前篇之——一起过一下面向对象的概念
创建型模式:
简易理解设计模式之:简单工厂模式——来试试接入支付功能
简易理解设计模式之:工厂方法模式——数据存储例子
简易理解设计模式之:抽象工厂模式——更换数据库例子
简易理解设计模式之:建造者模式——学习使用“链式调用”
简易理解设计模式之:原型模式——深、浅拷贝的概念
简易理解设计模式之:单例模式——单例模式的几种常用写法
结构型模式:
简易理解设计模式之:适配器模式——Android列表视图控件设计方式
简易理解设计模式之:桥接模式——穿衣服经典案例2
简易理解设计模式之:组合模式——实现View中的树状结构
简易理解设计模式之:装饰模式——穿衣服经典案例
简易理解设计模式之:外观模式——第三方SDK的帮助类
简易理解设计模式之:享元模式——五子棋游戏例子
简易理解设计模式之:代理模式——iOS视图控件设计方式
行为型模式:
简易理解设计模式之:策略模式——优化一下支付功能
简易理解设计模式之:模板方法模式——Android中的BaseActivity基类
简易理解设计模式之:观察者模式——监听与回调
简易理解设计模式之:状态模式——优化登录操作
简易理解设计模式之:备忘录模式——Word文档的工作原理
简易理解设计模式之:迭代器模式——遍历对象的好帮手
简易理解设计模式之:命令模式——实现命令的参数化配置
简易理解设计模式之:责任链模式——OA中请假流程示例
简易理解设计模式之:中介者模式——多人聊天室例子
简易理解设计模式之:解释器模式——语言和文法
简易理解设计模式之:访问者模式——员工考核例子

posted @ 2022-11-21 18:56  TwcatL_tree  阅读(6)  评论(0编辑  收藏  举报