一.概念
1.1耦合和解耦
1.1.1 耦合
- 耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。
- 在软件工程中,对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护成本越高,因此对象的设计应使类和构件之间的耦合最小。
1.1.2 解耦
- 解耦,字面意思就是解除耦合关系。
- 在软件工程中,降低耦合度即可以理解为解耦,模块间有依赖关系必然存在耦合,理论上的绝对零耦合是做不到的,但可以通过一些现有的方法将耦合度降至最低。
- 设计的核心思想:尽可能减少代码耦合,如果发现代码耦合,就要采取解耦技术。让数据模型,业务逻辑和视图显示三层之间彼此降低耦合,把关联依赖降到最低,而不至于牵一发而动全身。原则就是A功能的代码不要写在B的功能代码中,如果两者之间需要交互,可以通过接口,通过消息,甚至可以引入框架,但总之就是不要直接交叉写。
- 观察者模式:观察者模式存在的意义就是「解耦」,它使观察者和被观察者的逻辑不再搅在一起,而是彼此独立、互不依赖。比如网易新闻的夜间模式,当用户切换成夜间模式之后,被观察者会通知所有的观察者「设置改变了,大家快蒙上遮罩吧」。QQ消息推送来了之后,既要在通知栏上弹个推送,又要在桌面上标个小红点,也是观察者与被观察者的巧妙配合。
1.2 DI理解
DI—Dependency Injection(
依赖注入)
,其是一种设计思想,降低对象与对象之间的耦合度。意思自身对象中的内置对象是通过注入的方式进行创建,不是直接通过new 来创建内置对象。形象的说,即由容器动态的将某个依赖关系注入到组件之中。(不是必须要使用这种方式来实现,但是这样后期维护起来更加方便。)
依赖注入常见的有三种方式:
-
构造函数注入(Contructor Injection)
-
setter注入
-
接口注入
1.3 IOC理解
Ioc—Inversion of Control,即控制反转,其是一种设计思想,而不是一种技术。再没有使用IOC之前,我们一般是通过new来实例化,从而创建一个对象。但是我们使用IOC之后,创建这个对象的控制权将由内部转换到外部,那么这个过程便可以理解为控制反转。也即把对象转换成抽象对象的依赖.。
同时控制反转也是一个目标,控制反转的优点有如下两点:
- 可以很好的做到解耦,降低耦合度。
- 屏蔽对象的实现细节,只关心动作不关心动作中的细节。
二、内置IOC
2.1 内置的IOC 有三种生命周期
调试代码看看实际效果:
创建接口:ITransientServer,IScopedServer,ISingletonServer,添加Guid来体现实际效果
public interface ITransientServer
{
Guid MyProperty { get; }
List<string> GetList(string a);
}
public interface IScopedServer
{
Guid MyProperty { get; }
List<string> GetList(string a);
}
public interface ISingletonServer
{
Guid MyProperty { get; }
List<string> GetList(string a);
}
接口具体实现类:TransientServer,ScopedServer,SingletonServer
public class TransientServer : ITransientServer
{
public TransientServer()
{
MyProperty = Guid.NewGuid();
}
public Guid MyProperty { get; set; }
public List<string> GetList(string a)
{
return new List<string>() { "1_1", "1_2", "1_3" };
}
}
public class ScopedServer : IScopedServer
{
public ScopedServer()
{
MyProperty = Guid.NewGuid();
}
public Guid MyProperty { get; set; }
public List<string> GetList(string a)
{
return new List<string>() { "2_1", "2_2", "2_3" };
}
}
public class SingletonServer : ISingletonServer
{
public SingletonServer()
{
MyProperty = Guid.NewGuid();
}
public Guid MyProperty { get; set; }
public List<string> GetList(string a)
{
return new List<string>() { "3_1", "3_2", "3_3" };
}
}
注册服务,瞬时、作用域、单例的生命周期的服务:
public void ConfigureServices(IServiceCollection services)
{
//瞬时生命周期, Transient服务在每次被请求时都会被创建一个新的对象。这种生命周期比较适用于轻量级的无状态服务。
services.AddTransient<ITransientServer, TransientServer>();
// Scoped生命周期的服务是每次web请求被创建,局部单例对象, 在某个局部内是同一个对象(作用域单例,本质是容器单例);
// 一次请求内是一个单例对象,多次请求则多个不同的单例对象.
services.AddScoped<IScopedServer, ScopedServer>();
//Singleton生命能够周期服务在第一被请求时创建,在后续的每个请求都会使用同一个实例。
//如果你的应用需要单例服务,推荐的做法是交给服务容器来负责单例的创建和生命周期管理,而不是自己来走这些事情。
services.AddSingleton<ISingletonServer, SingletonServer>();
services.AddDirectoryBrowser();
services.AddRazorPages();
}
页面加载调用服务:
public class IndexModel : PageModel
{
public Viewdata viewdata = new Viewdata();
private readonly ITransientServer _transientServer;
private readonly IScopedServer _ScopedServer;
private readonly ISingletonServer _SingletonServer;
public IndexModel(ITransientServer transientServer, IScopedServer scopedServer2, ISingletonServer singletonServer3)
{
_transientServer = transientServer;
_ScopedServer = scopedServer2;
_SingletonServer = singletonServer3;
}
public void OnGet([FromServices] ITransientServer transientService11, [FromServices] IScopedServer scopedService22, [FromServices] ISingletonServer singletonServer33)
{
viewdata.date = _transientServer.GetList("");
viewdata.guid = _transientServer.MyProperty;
viewdata.guid11 = transientService11.MyProperty;
viewdata.guid2 = _ScopedServer.MyProperty;
viewdata.guid22 = scopedService22.MyProperty;
viewdata.guid3 = _SingletonServer.MyProperty;
viewdata.guid33 = singletonServer33.MyProperty;
}
}
public class Viewdata
{
public List<string> date { get; set; }
public Guid guid { get; set; }
public Guid guid11 { get; set; }
public Guid guid2 { get; set; }
public Guid guid22 { get; set; }
public Guid guid3 { get; set; }
public Guid guid33 { get; set; }
}
页面显示数据展示:
@page
@model IndexModel
@{
ViewData["Title"] = "Index";
}
@foreach (var item in @Model.viewdata.date)
{
<h2>@item</h2>
}
<h1>瞬时的:@Model.viewdata.guid</h1>
<h1>瞬时的11:@Model.viewdata.guid11</h1>
<h1>作用域的:@Model.viewdata.guid2</h1>
<h1>作用域的22:@Model.viewdata.guid22</h1>
<h1>全局唯一的:@Model.viewdata.guid3</h1>
<h1>全局唯一的33:@Model.viewdata.guid33</h1>
效果图片:
刷新图片后:
明显的可以看出:
- Transient:瞬时生命周期, Transient服务在每次被请求时都会被创建一个新的对象。这种生命周期比较适用于轻量级的无状态服务。
- Scoped: Scoped生命周期的服务是每次web请求被创建,局部单例对象, 在某个局部内是同一个对象(作用域单例,本质是容器单例);一次请求内是一个单例对象,多次请求则多个不同的单例对象.
- Singleton: Singleton生命能够周期服务在第一被请求时创建,在后续的每个请求都会使用同一个实例。如果你的应用需要单例服务,推荐的做法是交给服务容器来负责单例的创建和生命周期管理,而不是自己来走这些事情。