六大设计原则

开闭原则

开闭原则(Open-Closed Principle, Ocp)是指类、模块、函数等软件实体,对扩展开放,对修改关闭
强调用抽象构建框架,用实现扩展功能,提高软件系统的可复用性及可维护性。

即为开放扩展,扩展意为增加新的代码

即为关闭修改,修改意为修改现有的代码

实现方式

如果有新的业务需求或者业务需求需要修改,尽量要新增代码。如果想修改现有的功能,那就新增一个方法;如果想修改一个类,那就新增一个类;

实例

以课程体系为例,首先创建一个课程接口ICourse:

public interface Icourse{
	Integer getId();
	String getName();
	BigDecimal getPrice();
}

将我们原有的课程都实现该接口:

public class MathCourse implements ICourse{
	
	private Integer Id;
	private String name;
	private BigDecimal price;

	//获取价格
	public BigDecimal getPrice(){
		return this.price;
	}
}

现在需要给数学课做活动,加个优惠,不能修改原来的getPrice()方法影响原本的业务逻辑。那么,我们就再写一个新的类,继承重写父类的getPrice()方法

public class MathDiscountCourse extends MathCourse(){
	
	public BigDecimal getOriginPrice(){
		return super.getPrice();
	}
	
	public BigDecimal getPrice(){
		return super.getPrice() * 0.5;
	}
}

依赖倒置原则

依赖倒置原则(Dependence Inversion Principle, DIP)是指设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖抽象。
抽象不依赖细节,细节依赖抽象,通过这种方式,减少类与类之间的耦合性,降低修改造成的风险

实例

public class Tom{
	public void studyMathCourse(){
		println("Tom 学习 数学");
	}
	public void studyEnglishCourse(){
		println("Tom 学习 英语");
	}
}

调用:

public static void main(String[] args){
	Tom tom = new Tom();
	tom.studyMathCourse();
	tom.studyEnglishCourse();
}

依赖注入

如果Tom需要学习新的课程时,需要再Tom类中添加新的学习课程的方法,造成了修改代码的风险,根据依赖倒置原则,我们通过接口的方式实现:

public interface ICourse{
	void study();
}

public class MathCourse implements ICourse {
	@Override
	public void study(){
		println("Tom 学习 数学");
	}
}

public class EnglishCourse implements ICourse {
	@Override
	public void study(){
		println("Tom 学习 英语");
	}
}

//Tom类
public class Tom {
	public class study(ICourse course){
		course.study();
	}
}

//调用
public static void main(String args[]){
	Tom tom = new Tom();
	tom.study(new MathCourse());
	tom.study(new EnglishCourse());
}

通过这种方式,无论课程如何增加,只要通过传参方式调用方法,就不需要修改代码,该种方式叫做依赖注入

构造器注入

public class Tom {
	private ICourse course;

	public Tom(ICourse course){
		this.course = course;
	}

	public void study(){
		corse.study();
	}
}

//调用
public static void main(String[] args){
	Tom tom = new Tom(new MatCourse());
	tom.study();
}

如果ICourse是全局单例,那么可以采用这种方式,注意该方式线程不安全。如果对线程安全有要求,可采用双端锁单例

单一职责原则

单一职责(Simple Responsibility Pinciple,SRP)是指不要存在多于一个导致类变更的原因。
如果一个类Class1处理业务T1和业务T2,当业务T1改变时,需要修改Class1的代码,此时对T2造成了一定风险。所以遵循单一职责原则,Class1只处理T1,再编写Class2处理T2,降低修改带来的风险
总体来说,就是一个Class/Interface/Method 只负责一项职责

实例

假设我们有两种学习课程的方式,观看直播课和观看录播课。

public class Course{
	public void study(String courseName){
		if(courseName.equals("直播课")){
			println("不能快进");
		}else{
			println("可以快进");
		}
	}
}

//调用
public static void main(String args[]){
	Course course = new Course();
	course.study("直播课");
	course.study("录播课");
}

该课程类承担了直播课和录播课两种职责,当其中一种课程业务逻辑需要更改时,会对另一种课程造成风险。
根据单一设计原则,我们将其设计为两个类

//录播课
public class ReplayCourse{
	public void study(){
		println("可以快进");
	}
}
//直播课
public class LiveCourse{
	public void study(){
		println("不能快进");
	}
}
//调用
public static void main(String args[]){
	LiveCourse liveCourse = new LiveCourse(); 
	liveCourse.study(); 
	ReplayCourse replayCourse = new ReplayCourse(); 
	replayCourse.study();
}

根据业务发展,可能需要扩充一些方法实现功能,假设需要补充两方面的方法:

  1. 课程本身的信息(课程名称、介绍、类型等)
  2. 课程的权限管理(购买、观看、退课等)

此时,我们再设计一个顶层接口ICourse,定义这些方法

public interface ICourse{
	//查看课程描述
	String getInfo();
	
	//购买课程
	void buyCourse();
}

根据单一设计原则,我们又可以将其拆分为两个接口

//课程本身的信息
public interface ICourseInfo{
	//查看课程描述
	String getInfo();
}
//课程权限管理
public interface ICourseManage{
	//购买课程
	void buyCourse();
}

根据这种设计思想,方法级、类级、库级、项目级在业务较为复杂时,尽量满足单一设计原则,可以更好的维护项目

接口隔离原则

接口隔离原则(Interface Segregation Principle, ISP)是指用多个专门的接口,而不使 用单一的总接口,客户端不应该依赖它不需要的接口。

  1. 一个类对一类的依赖应该建立在最小的接口之上
  2. 建立单一接口,不要建立庞大臃肿的接口
  3. 尽量细化接口,接口中的方法尽量少

举例

public interface IAnimal{
	//跑步
	void run();

	//飞
	void fly();

	//游泳
	void swim();
}

当需要编写一些动物类实现该接口时,不得不继承该接口的全部方法,但是不是每个动物类都需要该接口中的全部方法
根据接口隔离原则,将IAnimal接口再进行拆分

public interface FlyAnimal{
	//飞
	void fly();
}

public interface RunAnimal{
	//跑
	void run();
}

public interface SwimingAnimal{
	//游泳
	void swim();
}

通过这种方式,在编写动物类时,只继承需要的接口,避免重写不需要的方法,减少接口间的耦合性

迪米特法则

迪米特原则(Law of Demeter LoD)是指一个对象应该对其他对象保持最少的了解,又 叫最少知道原则(Least Knowledge Principle,LKP),尽量降低类与类之间的耦合。

实现

减少类与类之间不必要的依赖

里氏替换原则

为一个软件实体如果适用一个 父类的话,那一定是适用于其子类,所有引用父类的地方必须能透明地使用其子类的对 象,子类对象能够替换父类对象,而程序逻辑不变。

  1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  2. 子类中可以增加自己特有的方法。
  3. 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类 方法的输入参数更宽松。
  4. 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即 方法的输出/返回值)要比父类更严格或相等。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值