1.单一职责原则(Single Responsibility Principle, SRP):
(动物类就只需要实现和动物相关的信息,不可用来实现物品的信息
)
一个类只负责一个功能领域中的相应职责,
2.开闭原则(Open-Closed Principle, OCP):
(1.参数尽量以包装的方式传递,2.实体和接口尽量不要修改,3.以扩展的形式进行程序修改和实现
)
一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
3.里氏代换原则(Liskov Substitution Principle, LSP):
(使用子类替换基类/父类不会出现错误和异常,反之则不可
)
所有引用基类(父类)的地方必须能透明地使用其子类的对象
里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象
4.接口隔离原则(Interface Segregation Principle, ISP):
(接口尽可能的细小,独立,专一/专门
)
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
5.迪米特法则(Law of Demeter, LoD):
(不要和“陌生人”说话、只与你的直接朋友通信等
)
一个软件实体应当尽可能少地与其他实体发生相互作用。
6.依赖倒置:
(通过接口或基类的方式调用方法
)
依赖倒置原则是五大原则之一:
1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象.
2.抽象不能依赖于具象,具象依赖于抽象.
什么是上层?使用者就是上层,上例中,Test 类就是上层.
什么是下层?被使用者就是下层.上例中,Test 类使用了 MyDependency 类, MyDependency 类就是下层.
上层不应该依赖下层,Test 类不应该依赖 MyDependency 类,因为如果 MyDependency 类变化了,就是把这种变化所造成的影响传递到上层 Test 类.
因此,上例按照依赖倒置原则修改如下:
public class Test
{
private IDepenency md = new MyDependency();
public void Print()
{
md.Print();
}
}
public interface IDepenency
{
void Print();
}
public class MyDependency : IDepenency
{
public void Print()
{
Console.WriteLine("this is mydependency");
}
}
控制反转(IoC):Inversion of Control
(将对象以参数的形式传递给使用的类,通过接口类型调用)
控制反转是一种思想,所谓"控制反转",就是反转获得依赖对象的过程.或许,叫"反转控制"更容易理解.
上例虽然遵循了"依赖倒置原则",但是违背"开放封闭原则",因为如果有一天想修改 md 为 YourDependency 类的实例,则需要修改 Test 类.因此,我们需要反转这种创建对象的过程.
internal class Program
{
private static void Main(string[] args)
{
Test test = new Test(new MyDependency());
test.Print();
Console.ReadKey();
}
}
public class Test
{
private IDepenency md;
public Test(IDepenency depenency)
{
md = depenency;
}
public void Print()
{
md.Print();
}
}
上例中,将 md 的创建过程"反转"给了调用者.
依赖注入(DI):Dependency Inject
(通过配置的思路,将类动态的获取,然后以参数的方式传入)
依赖注入设计模式是一种在类及其依赖对象之间实现控制反转(IOC)思想的技术.
所谓依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。
我们先创建一个简易的IoC容器(当然,实际的 IoC 容器复杂得多.):
public class IoCContainer
{
private Dictionary<Type, Object> dic;
public IoCContainer()
{
Init();
}
private void Init()
{
dic = new Dictionary<Type, object>
{
{typeof(IDepenency),new MyDependency() }
};
}
public T GetInstance<T>()
{
return (T)dic[typeof(T)];
}
}
那么,上例的调用,则可以修改成:
internal class Program
{
private static void Main(string[] args)
{
IoCContainer container = new IoCContainer();//创建一个容器
IDepenency dependency = container.GetInstance<IDepenency>();//获取注册的实例
Test test = new Test(dependency);
test.Print();
Console.ReadKey();
}
}
依赖注入分为3中:构造函数注入,属性注入,方法注入,上例属于构造函数注入.
ASP.NET Core 中的依赖注入
ASP.NET Core 内置的IoC容器,只支持构造函数注入,注入的方式如下:
在 Startup 类的 ConfigureServices 方法中注册.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
//DI
services.AddTransient<IDependency, MyDependency>();
}
使用:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IDepenency _dependency;
public ValuesController(IDepenency dependency)
{
_dependency = dependency;
}
...other codes
}
参考文章 (返回主页 Matrix海 子)设计模式之六大原则(转载)
(NET未来之路)ASP.NET Core 2.2 基础知识(一) 依赖注入