切换导航
简历
工具
演示
查询
导航菜单
服务端
30
前端
114
数据库
82
进阶开发
8
桌面程序
2
QA
15
软件使用
36
规范协议
5
操作系统
11
AI
0
复用资源
6
硬件
0
标签
设计模式
框架
大数据
物联网
实现方案
算法
分布式
第三方应用
消息中间件
外部链接
.NET Core SDK和运行时安装包
淘宝 NPM 镜像
查询网
Tables Generator线上表格转换工具
引用cdn在线脚本和样式
首页
进阶开发
OOP面向对象和AOP面向切面介绍
[TOC] ## 1. OOP 面向对象 面向对象:OOP(Object Oriented Programming)是一种程序设计范型,它以对象为基础,将数据和操作封装在对象中,并利用类和继承等概念来构建和管理程序,面向对象是一种编程思想,它将现实世界中的对象映射到程序中的类和对象。它包括三个基本特征:封装、继承和多态。 ### 1.1. 面向对象特性封装 封装是将数据和操作封装在对象中,从而隐藏对象的内部实现细节。通过将状态(属性)和行为(方法)封装在对象中,可以保护对象的状态不受外部干扰,同时也可以确保对象的行为不会对其他对象产生影响。 在C#中,可以通过使用访问修饰符(private、protected、public)来控制对类的访问权限。例如: ```csharp public class Person { private string name; private int age; public Person(string name, int age) { this.name = name; this.age = age; } public string GetName() { return this.name; } public int GetAge() { return this.age; } } ``` 在上面的例子中,我们定义了一个名为`Person`的类,并使用访问修饰符将属性(name和age)封装在类内部。外部代码无法直接访问这些属性,只能通过公共方法(GetName和GetAge)来获取属性值。 ### 1.2. 面向对象特性继承 继承是面向对象编程中的另一个重要概念。它允许我们创建一个新的类(子类),从现有类(父类)继承属性和方法。子类可以添加新的属性和方法,也可以重写父类中的方法。 在C#中,可以使用关键字“class”和“:”来定义一个继承关系。例如: ```csharp public class Animal { public void Eat() { Console.WriteLine("Animal is eating."); } } public class Dog : Animal { public void Bark() { Console.WriteLine("Dog is barking."); } } ``` 在上面的例子中,我们定义了一个`Animal`类作为基类,然后创建了一个`Dog`类作为`Animal`类的子类。`Dog`类继承了`Animal`类的Eat方法,并添加了一个新的方法Bark。通过继承,我们可以更好地组织和管理代码,并实现代码的重用。 ### 1.3. 面向对象特性多态 多态是指同一个方法在运行时可以具有不同的表现形式。在面向对象编程中,多态性通常是通过重写方法和接口来实现的。通过使用多态,我们可以将对象视为其所属类的类型,而不是其实际类型。这使得代码更加灵活和可扩展。 在C#中,可以使用关键字“override”来重写父类中的方法。例如: ```csharp using System; // 定义一个基类 Animal public abstract class Animal { public abstract void Speak(); } // 定义一个派生类 Dog,重写 Animal 中的 Speak 方法 public class Dog : Animal { public override void Speak() { Console.WriteLine("Dog is barking!"); } } ``` 在这个示例中,我们定义了一个抽象类`Animal`,其中包含一个抽象方法`Speak()`。然后,我们创建了一个派生类`Dog`,并使用`override`关键字重写了`Speak()`方法。这样,当我们创建一个`Dog`对象并调用`Speak()`方法时,将会输出"Dog is barking!"。 > Tips > 子类重写父类的方法,需要父类的方法是虚方法(virtual)或父类是抽象类(abstract)和抽象的方法,抽象的方法没有主体,和接口方法声明类似。 ### 1.4. 面向对象示例 ```csharp // 定义一个名为Person的类 public class Person { // 定义两个私有成员变量 public string name; public int age; // 定义一个公共构造函数 public Person(string name, int age) { this.name = name; this.age = age; } // 定义一个公共方法来获取姓名 public virtual string GetName() { return this.name; } // 定义一个公共方法来获取年龄 public virtual int GetAge() { return this.age; } } // 定义一个名为Student的类,继承自Person类 public class Student : Person { // 定义一个私有成员变量来存储学号 private int studentId; // 定义一个公共构造函数,调用父类的构造函数 public Student(string name, int age, int studentId) : base(name, age) { this.studentId = studentId; } // 重写父类的GetAge方法,并添加学生特有的行为 public override int GetAge() { Console.WriteLine("学生需要等到6岁才能入学哦!"); return this.age + 6; } } // 定义一个名为Teacher的类,继承自Person类 public class Teacher : Person { // 定义一个私有成员变量来存储教龄 private int teachingYears; // 定义一个公共构造函数,调用父类的构造函数 public Teacher(string name, int age, int teachingYears) : base(name, age) { this.teachingYears = teachingYears; } // 重写父类的GetAge方法,并添加教师特有的行为 public override int GetAge() { Console.WriteLine("教师已经有" + this.teachingYears + "年的教龄了!"); return this.age + this.teachingYears; } } ``` 这个示例代码中,我们定义了三个类:`Person`、`Student`和`Teacher`。`Person`类是基类,包含了两个私有成员变量(name和age)和一个公共构造函数。然后,我们创建了两个派生类:`Student`和`Teacher`,它们都继承自`Person`类。在派生类中,我们重写了父类的`GetAge`方法,并添加了各自特有的行为。最后,在主程序中创建了一个学生对象和一个教师对象,并调用它们的`GetAge`方法。 ## 2. AOP 面向切面 面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。 但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。 也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。 一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。 AOP在编程历史上可以说是里程碑式的,对OOP编程是一种十分有益的补充。 ### 2.1. 什么是面向切面 **面向切面:**AOP(Aspect Oriented Programming)是一种编程范式,它的主要目标是解决在面向对象编程(OOP)中出现的`横切关注点`(cross-cutting concerns)的问题。在OOP中,我们通常将具有相同行为或特征的实体抽象为类或对象。然而,有些关注点是跨越多个类的,例如日志记录、事务管理、安全性等。这些关注点被称为横切关注点,因为它们横跨多个对象,不能被单一的对象或类所处理。 AOP解决了这个问题,它允许我们将这些横切关注点从核心业务逻辑中分离出来,从而提高代码的可维护性和可重用性。 *** #### 2.1.1. 什么是横切关注点 在面向切面编程(AOP)中,横切关注点是指跨越多个对象或类的公共逻辑或功能,这些关注点与程序中的核心业务逻辑无关。横切关注点通常是可以从程序中提取出来的功能,这些功能可以在不同的对象或类之间共享,从而提高代码的可重用性和可维护性。 例如,在日志记录切面中,横切关注点是记录日志的逻辑。这个逻辑可能会被应用到多个不同的对象或类中,无论这些对象或类是否与日志记录直接相关。通过将这个逻辑提取出来并应用到需要的地方,我们可以避免在每个需要记录日志的地方重复编写相同的代码,从而提高代码的可维护性和可重用性。 因此,可以说AOP中的横切关注点是提取出来的功能,这些功能可以被应用到不同的对象或类中,以实现代码的模块化和可重用性。 *** ### 2.2. C#中常见的面向切面框架 + AspectSharp 是免费和开源的。它以 Dynamic Proxies 和 XML 作为配置文件,是一个在 .NET 环境下的 AOP 框架。 + PostSharp 它提供了一个简单的方法来实现切面编程,通过在代码中使用PostSharp的注解(attributes)来标记需要应用切面的方法或类 > PostSharp的工作原理是在编译时对目标代码进行静态修改。它使用MSBuildTask和MSILInjection技术,将切面代码插入到目标代码中。这种静态修改的方式相比于动态修改(如使用Proxy模式)具有更高的执行效率。 + Castle 是一个针对.NET平台的开源项目,它提供了一个集成了多种功能的AOP实现。通过使用Castle框架,开发者可以方便地实现AOP,从而提高代码的可维护性和可重用性。 > 在Castle框架中,AOP的实现主要依赖于一种称为“动态代理”的技术。它通过在运行时创建一个代理对象,来对具体对象的行为进行增强或修改。Castle框架提供了一些类和接口,使得开发者可以方便地创建自己的切面,并将其应用到目标对象上。 + Encase 是C#编写开发的为.NET平台提供的AOP框架。Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式。这种部署方面(aspects)的方法帮助缺少经验的开发人员提高开发效率。 + NKalore 是一款编程语言,它扩展了C#允许在.net平台使用AOP。NKalore的语法简单、直观,它的编译器是基于Mono C#编译器(MCS)。NKalore目前只能在命令行或#Develop内部使用。NKalore兼容公共语言规范CLS(Common Language Specification),它可以在任何.NET开发环境中使用,包括微软的Visual Studio .NET。 + AspectDNG 的目标是为.NET开发人员提供简单而功能强大的AOP-GAOP实现。它效仿Java下的开源工具AspectJ 和 Spoon,成熟程度也很接近它们。 + RAIL(Runtime Assembly Instrumentation Library) 开源项目可以在C#程序集加载和运行前进行处理控制调整和重新构建。C#在CLR中,我们已经能够动态加载程序集并且获得程序集中的类和方法,RAIL(Runtime Assembly Instrumentation Library)的出现填补了CLR处理过程中的一些空白。 + SetPoint是一款.NET框架下的全功能(full-featured)AOP引擎.它着重为称为语义切点(semantic pointcuts)的定义依赖RDF/OWL的使用.它的功能为一个IL-level,highly dynamic weaver&LENDL,一个引人注目的定义语言 + DotNetAOP为 CLR language提供AOP 框架基础属性。 + NAop是一个DotNet下的AOP框架。 > 注意:PostSharp是收费的,免费的版本也有,但功能受限,而且即使免费版本用于商业也是需要缴费的 ### 2.3. 面向切面的简单示例 + 首先,定义一个接口`ILoggingAspect`,该接口表示一个日志切面: ```csharp public interface ILoggingAspect { void LogBeforeMethodExecution(); void LogAfterMethodExecution(); } ``` + 接下来,定义一个实现了`ILoggingAspect`接口的类`LoggingAspect`,该类实现了切面的逻辑: ```csharp public class LoggingAspect : ILoggingAspect { public void LogBeforeMethodExecution() { Console.WriteLine("Entering method"); } public void LogAfterMethodExecution() { Console.WriteLine("Exiting method"); } } ``` + 然后,定义一个目标类`MyClass`,并在其中定义一个方法`MyMethod`: ```csharp public class MyClass { public void MyMethod() { Console.WriteLine("Doing some work..."); } } ``` + 接下来,在`MyClass`中实现一个代理类`MyClassProxy`,该代理类将拦截对`MyMethod`的调用,并在调用前后执行切面的逻辑: ```csharp public class MyClassProxy : IMyClass { private MyClass _myClass; private ILoggingAspect _loggingAspect; public MyClassProxy(MyClass myClass, ILoggingAspect loggingAspect) { _myClass = myClass; _loggingAspect = loggingAspect; } public void MyMethod() { _loggingAspect.LogBeforeMethodExecution(); _myClass.MyMethod(); _loggingAspect.LogAfterMethodExecution(); } } ``` + 最后,定义一个接口`IMyClass`,该接口表示目标类`MyClass`的方法: ```csharp public interface IMyClass { void MyMethod(); } ``` 在上面的示例中,我们通过定义一个代理类`MyClassProxy`来实现对目标方法`MyMethod`的拦截。在代理类中,我们使用切面对象`_loggingAspect`来执行切面的逻辑,即在调用前后输出日志信息。最后,我们将代理类传递给目标类的构造函数,以便在调用目标方法时能够执行代理类中的逻辑。 ## 3. 面向对象和面向切面的区别 面向对象和面向切面是两种不同的编程范式,它们有各自的特点和适用场景。 **面向对象:** + 面向对象是一种编程范式,它将数据和对数据的操作封装在一起,以对象为单位组织程序。面向对象编程(OOP)强调的是对象之间的关系和交互,关注的是“谁来做”,也就是完成任务的对象,而非细节。 + 在面向对象编程中,我们通常会定义一些类,每个类包含一些属性和方法。这些类可以相互关联和交互,以完成特定的任务。面向对象编程的优点在于易于维护、易于扩展和易于重用。 **面向切面:** + 面向切面是一种编程范式,它关注的是程序中的横切关注点,例如日志记录、事务管理、安全性、异常处理等。面向切面编程(AOP)的核心思想是将这些横切关注点分离出来,并自动应用到相关的对象或方法上,以达到模块化、可复用和可维护的目的。 + 面向切面编程通常使用代理模式实现,通过在主函数前后添加额外的方法来实现横切关注点的功能。面向切面编程的优点在于可以减少代码重复、提高代码的可维护性和可重用性。 在实际应用中,我们应该根据项目的特点和需求选择适合的编程范式。如果项目需要处理大量的数据和复杂的逻辑,面向对象比较适合,因为它强调的是对象之间的关系和交互,可以更好地组织和管理代码。如果项目需要处理一些横切关注点,例如日志记录、事务管理、安全性等,面向切面比较适合,因为它可以将这些关注点分离出来,并自动应用到相关的对象或方法上,提高代码的可维护性和可重用性。
扫一扫手机看
点击排行
windows 文件资源管理器使用
Layui 弹窗open使用说明
SQL Server 中字符串函数使用
C# 使用QQ邮箱代理做邮件接收功能
SQL Server关于apply的两种形式cross apply 和 outer apply
ASP.NET MVC 模型的自定义验证
nvm安装及常用命令
SQL Server 中数据类型转换
SQL Server 中WITH AS短语的使用
IE浏览器下AJAX缓存问题导致数据不更新的解决办法
订阅号