设计原则
使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性。在进行设计的时候,我们需要遵循以下几个原则:单一职责原则、开闭原则、里氏替代原则、依赖倒置原则、接口隔离原则、合成复用原则和迪米特法则。
1.单一职责原则
专业的人做专业的事,面向对象编程中类也是一样,一个类只负责一些特定的职责,如User类只负责用户相关的业务功能,Order类只负责订单相关的功能,想象下如果我们把用户和订单的功能放在一个类,然后去设计用户的权限中会怎么样呢?订单业务和权限耦合了。。单一职责原则作用是降低职责间的耦合,同时提高代码的复用率。
2.开闭原则
开闭原则通俗的讲就是对添加(扩展)开放,对修改关闭。如我们维护一个软件系统,这时要添加一个新功能,我们可以写新代码来添加这个功能,但是不能修改以前的代码,想象下我们为了新功能修改了一些旧代码,然后发现一些旧的功能挂掉了时的心情。
3.依赖倒置
依赖倒置原则作用是方便实现类的切换,降低业务要求和具体实现间的耦合。抽象不应该依赖细节,而细节应该依赖抽象,这就是我们为什么使用面向接口编程,而不是面向实现编程的原因。
4.接口隔离原则
接口隔离原则指的是提倡使用多个专门的接口,而不是使用一个总的接口。以一个订单系统为例,我们自己的系统可以对订单进行增删改查操作,给第三方只提供了查询操作。如果把增删改查的功能都定义在一个接口中那么第三方的实现类也要做增删改的实现。分成两个接口就避免了这种情况。
public interface IOrderService1 { void Add();//添加 void Delete();//删除 void Edit();//修改 } public interface IOrderService2 { void Query(); } //我们用的订单服务类 public class MyOrderService : IOrderService1, IOrderService2 { public void Add(){//添加操作} public void Delete(){//删除操作} public void Edit() {//修改操作} public void Query(){//查询操作} } //给第三方提供的订单服务类 public class OtherOrderServeice : IOrderService2 { public void Query(){//查询操作} }
5.合成复用原则
合成复用指的是一个对象A包含了另一个对象B,那么A就可以委托B来使用B的功能。一个例子:
//订单类 public class Order { public User user;//订单中有用户 } //用户类 public class User { public string UserName { get; set; } public string getName() { return this.UserName; } }
上边的例子中订单中包含了用户,我们可以使用order.User.getName();order委托其属性user来调用User类中的方法。注意合成复用用于“has-a”场景,例子中订单has-a用户,订单和用户是包含关系;“is-a"场景则要使用继承,如学生is-a人类,学生要继承于人类。
6.迪米特法则(最小知道原则)
迪米特法则指的是各个类之间应该尽可能的不了解,最好是相互独立的。但是很多时候类与类之间不可避免的要传输信息,如上边的Order和User就存在强依赖关系,我们应该尽可能地降低类和类间的依赖。怎么降低依赖呢?一种常用的方式是通过中间件(如redis/rabbitmq等)来降低依赖。如A和B类要通信,原始的方式是new一个实例出来直接通信 A<-->B ,现在我们用一个中间件充当传话人那么A和B通信就变成了 A<-->中间件<-->B 形式,这样A和B就降低了耦合。
设计模式中的外观模式和中介者模式就使用了迪米特法则。
7.里氏替代原则
里氏替代原则指的是父类存在的地方,子类都可以替换,并且行为不发生改变,只有所有的父类都可以被子类替代且行为不发生变化时才能说明父类是可复用的。一个违背里氏替换原则的例子:我们定义了鸟类有fly方法,表示鸟类都可以飞,但是企鹅也是鸟类而且企鹅不会飞,这时企鹅(子类)就不能替代其鸟类(父类)了,说明我们设计的鸟类违背了里氏替代原则。
原文地址:https://www.cnblogs.com/wyy1234/p/9961078.html