重学Android基础系列篇(四):架构动态编程进阶补充:编译时处理

前言

本系列文章主要是汇总了一下大佬们的技术文章,属于Android基础部分,作为一名合格的安卓开发工程师,咱们肯定要熟练掌握java和android,本期就来说说这些~

[非商业用途,如有侵权,请告知我,我会删除]

DD一下: Android进阶开发各类文档,也可关注公众号<Android苦做舟>获取。

1.Android高级开发工程师必备基础技能
2.Android性能优化核心知识笔记
3.Android+音视频进阶开发面试题冲刺合集
4.Android 音视频开发入门到实战学习手册
5.Android Framework精编内核解析
6.Flutter实战进阶技术手册
7.近百个Android录播视频+音视频视频dome
.......

架构动态编程技术原理

动态编程进阶:编译时处理

1.面向切面编程
1.1 AOP定义

AOP:Aspect Oriented Programming的缩写,意为面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP思想的延续。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

为什么要学习AOP呢?

AOP的应用场景非常广泛,在一些高级工程师或者架构师的面试过程中,频率出现的比较多。

1.2 编程思想的发展路线

1、POP

POP:Procedure Oriented Programming的缩写,即面向过程编程,是一种以过程为中心的编程思想。

面向过程是分析出解决问题的步骤,然后用函数或者方法,把这些步骤一步一步的实现,使用的时候在一个一个的一次调用函数或者方法,这就是面向过程编程。最开始的时候都是面向过程编程。面向过程是最为实际的一种思考方式。就算是面向对象编程,里面也是包含有面向过程的编程思想,因为面向过程是一种基础的编程思考方式,它从实际出发来考虑如何实现需求。

POP的不足:面向过程编程,只能处理一些简单的问题,无法处理一些复杂的问题。如果问题很复杂,全部以流程来思考的话,会发现流程很混乱,甚至流程都不能进行下去。

2、OOP

OOP:Object Oriented Programming的缩写,即面向对象编程。

早期的计算机编程都是面向过程的,因为早期的编程都比较简单。但是随着时间的发展,需求处理的问题越来越多,问题就会越来越复杂,这时就不能简单的使用面向过程的编程了,就出现了面向对象编程。在计算机里面,把所有的东西都想象成一种事物。现实世界中的对象都有一些属性和行为,也就对应计算机中的属性和方法。

面向对象编程就是把构成问题的事物分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

我们以一栋大楼为例来说明OOP的不足。

我们把系统比喻成一栋楼,类或者对象是砖块,砖块组成了一面墙,多面墙构成一间房间,多个房间构成一栋楼。 这就好比一个模块的功能是由多个类实现,模块又组成了某一项服务,多个服务构成了一个完整的系统。一个系统开发完成并不代表就真的完成了,以后肯定会有各种需求的变更出现,需求变更出现以后就要去修改代码,代码都在类里面,这就相当于去修改类。如果是小范围的修改影响还不是很大,如果是大范围的修改,影响就比较大了。即使每次修改都很小,但是如果经常进行修改,影响也会很大。就会造成系统的不稳定。我们得出结论:类应该是固定的,不应该频繁的去修改,甚至是不允许修改。这也是为什么有那么多的设计原则和设计模式。大部分的设计模式都是为了解决这类问题的,即在不修改类的前提下去扩展功能。

OOP的不足:产生新的需求会导致程序代码不断的进行修改,容易造成程序的不稳定。

如果非常了解OOP的话,那么我们应该知道,从对象的组织角度来讲,分类方法都是以继承关系为主线的,我们称为纵向。如果只使用OOP思想的话,会带来两个问题: 1、共性问题。 2、扩展问题,需要对先有类进行扩展时就比较困难了。

OOP与POP的区别:

在对比面向过程的时候,面向对象的方法是把事物最小化为对象,包括属性和方法。当程序的规模比较小的时候,面向过程编程还是有一些优势的,因为这时候程序的流程是比较容易梳理清楚的。以早上去上班为例,过程就是起床、穿衣、刷牙洗脸、去公司。每一步都是按照顺序完成的,我们只需要按照步骤去一步一步的实现里面的方法就行了,最后在依次调用实现的方法即可,这就是面向过程开发。

如果使用面向对象编程,我们就需要抽象出来一个员工类,该员工具有起床、穿衣、刷牙洗脸、去公司的四个方法。但是,最终要实现早上去上班的这个需求的话,还是要按照顺序依次来调用四个方法。最开始的时候,我们是按照面向过程的思想来思考该需求,然后在按照面向对象的思想来抽象出几个方法,最终要实现这个需求,还是要按照面向过程的顺序来实现。

面向对象和面向过程的区别仅仅是在思考问题方式上面的不同。最终你会发现,在你实现这个需求的时候,即使使用了面向对象的思想抽象出来了员工类,但是最后还是要使用面向过程来实现这个需求。

3、AOP

AOP:Aspect Oriented Programming的缩写,即面向切面编程。是对OOP的一种补充,在不修改原始类的情况下,给程序动态添加统一功能的一种技术。

OOP关注的是将需求功能划分为不同的并且相对独立、封装良好的类,依靠继承和多态来定义彼此的关系。AOP能够将通用需求功能从不相关的类中分离出来,很多类共享一个行为,一旦发生变化,不需要去修改很多类,只需要去修改这一个类即可。

AOP中的切面是指什么呢?切面指的是横切关注点。看下面一张图:

OOP是为了将状态和行为进行模块化。上图是一个商场系统,我们使用OOP将该系统纵向分为订单管理、商品管理、库存管理模块。在该系统里面,我们要进行授权验证。像订单、商品、库存都是业务逻辑功能,但是这三个模块都需要一些共有的功能,比如说授权验证、日志记录等。我们不可能在每个模块里面都去写授权验证,而且授权验证也不属于具体的业务,它其实属于功能性模块,并且会横跨多个业务模块。可以看到这里是横向的,这就是所谓的切面。通俗的将,AOP就是将公用的功能给提取出来,如果以后这些公用的功能发生了变化,我们只需要修改这些公用功能的代码即可,其它的地方就不需要去更改了。所谓的切面,就是只关注通用功能,而不关注业务逻辑,而且不修改原有的类。

AOP优势:

  • 将通用功能从业务逻辑中抽离出来,提高代码复用性,有利于后期的维护和扩展。
  • 软件设计时,抽出通用功能(切面),有利于软件设计的模块化,降低软件架构的复杂度。

AOP的劣势:

  • AOP的对OOP思想的一种补充,它无法单独存在。如果说单独使用AOP去设计一套系统是不可能的。在设计系统的时候,如果系统比较简单,那么可以只使用POP或者OOP来设计。如果系统很复杂,就需要使用AOP思想。首先要使用POP来梳理整个业务流程,然后根据POP的流程,去整理类和模块,最后在使用AOP来抽取通用功能。

AOP和OOP的区别:

  • 面向目标不同:OOP是面向名词领域(抽象出来一个事物,比如学生、员工,这些都是名词)。AOP是面向动词领域(比如鉴权、记录日志,这些都是动作或行为)。
  • 思想结构不同:OOP是纵向的(以继承为主线,所以是纵向的)。AOP是横向的。
  • 注重方面不同:OOP是注重业务逻辑单元的划分,AOP偏重业务处理过程中的某个步骤或阶段。

POP、OOP、AOP三种思想是相互补充的。在一个系统的开发过程中,这三种编程思想是不可或缺的。

1.3 实现AOP

我们在上面讲解了有关AOP的一些理论知识,那么如何在代码里面实现呢?

实现AOP有两种方式:

  • 静态代理实现。所谓静态代理,就是我们自己来写代理对象。
  • 动态代理实现。所谓动态代理,就是在程序运行时,去生成一个代理对象。
1.3.1 静态代理

实现静态代理需要使用到两种设计模式:装饰器模式和代理模式。

装饰器模式:允许向一个现有的对象添加新的功能,同时又不改变这个现有对象的结构。属于结构型设计模式,它是作为现有类的一种包装。首先会创建一个装饰类,用来包装原有的类,并在保持类的完整性的前提下,提供额外的功能。看下面的例子。

我们首先创建一个User类:

using` `System;``using` `System.Collections.Generic;``using` `System.Linq;``using` `System.Text;``using` `System.Threading.Tasks;` `namespace` `StaticDemo.Model``{``  ``public` `class` `User``  ``{``    ``public` `string` `Name { ``get``; ``set``; }``    ``public` `string` `Password { ``get``; ``set``; }``  ``}``}

接着我们创建一个账号服务的接口,里面有一个方法,用来注册一个用户:

using` `StaticDemo.Model;` `namespace` `StaticDemo.Services``{``  ``/// <summary>``  ``/// 接口``  ``/// </summary>``  ``public` `interface` `IAccountService``  ``{``    ``/// <summary>``    ``/// 注册用户``    ``/// </summary>``    ``/// <param name="user"></param>``    ``void` `Reg(User user);``  ``}``}

然后创建一个类来实现上面的接口:

using` `StaticDemo.Model;``using` `System;` `namespace` `StaticDemo.Services``{``  ``/// <summary>``  ``/// 实现IAccountService接口``  ``/// </summary>``  ``public` `class` `AccountService : IAccountService``  ``{``    ``public` `void` `Reg(User user)``    ``{``      ``// 业务代码 之前 或者之后执行一些其它的逻辑``      ``Console.WriteLine($``"{user.Name}注册成功"``);``    ``}``  ``}``}

我们在创建一个装饰器类:

using` `StaticDemo.Model;``using` `StaticDemo.Services;``using` `System;` `namespace` `StaticDemo``{``  ``/// <summary>``  ``/// 装饰器类``  ``/// </summary>``  ``public` `class` `AccountDecorator : IAccountService``  ``{``    ``private` `readonly` `IAccountService _accountService;` `    ``public` `AccountDecorator(IAccountService accountService)``    ``{``      ``_accountService = accountService;``    ``}` `    ``public` `void` `Reg(User user)``    ``{``      ``Before();``      ``// 这里调用注册的方法,原有类里面的逻辑不会改变``      ``// 在逻辑前面和后面分别添加其他逻辑``      ``_accountService.Reg(user);``      ``After();``    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值