参考:B站动力节点
设计模式介绍
- 代表了代码的最佳实践,被有经验的开发人员所使用
- 设计模式是很多被反复使用并知晓的,主要是对代码和经验的总结
- 使用设计模式是为了重用代码,让代码更容易被他人理解,保证代码的可靠性
- 对接口编程而不是对实现编程
- 优先使用对象组合而不是继承
七大原则
- 开闭原则
- 对扩展开放,对修改关闭
- 编写软件,比如类,模块,方法
- 使用抽象进行构建,使用实现扩展细节
- 面向抽象编程
- 提高软件系统的可复用性和可维护性
- 对扩展开放,对修改关闭
public interface Human {
public void eat();
public void sleep();
}
public class Student implements Human {
@Override
public void eat() {
System.out.println("学生在吃饭");
}
@Override
public void sleep() {
System.out.println("学生在睡觉");
}
public void study() {
System.out.println("学生在学习");
}
}
public class HighSchoolStudent extends Student {
@Override
public void study() {
System.out.println("高中生在学习");
}
}
- 依赖倒转原则
- 是开闭原则的基础,针对接口编程
- 依赖抽象,而不是具体的实现类
- 减少类与类之间的耦合性,提高系统稳定性,提高代码可读性和可维护性
- 降低修改程序所造成的风险
public class Programmer implements Human{
@Override
public void eat() {
System.out.println("程序员在吃饭");
}
@Override
public void sleep() {
System.out.println("程序员在睡觉");
}
public abstract void work();
}
public class JavaProgrammer extends Programmer{
@Override
public void work() {
System.out.println("程序员在写Java代码");
}
}
- 单一原则
- 一个类、接口、方法,只负责一项职责
- 降低程序的复杂度,提高程序可维护性,降低了变更所带来的风险
public abstract class Programmer implements Human{
public abstract void work();
}
public class JavaProgrammer extends Programmer{
private Order order;
public void setOrder(Order order) {
this.order = order;
}
@Override
public void eat() {
// order.local();
order.take();
System.out.println("程序员在吃饭");
}
@Override
public void sleep() {
System.out.println("程序员在睡觉");
}
@Override
public void work() {
System.out.println("程序员在写Java代码");
}
}
// 将订单的操作交由专门的订单类处理
public class Order{
public void local() {
System.out.println("堂食");
}
public void take() {
System.out.println("订外卖");
}
}
- 接口隔离原则
- 使用多个接口,而不是单一的接口
- 尽量细化接口,接口中方法尽可能少
- 符合低耦合设计思想,提高了可扩展性,以及可维护性
public abstract class Human implements EatInterface, SleepInterface{
}
public interface EatInterface{
public void eat();
}
public interface SleepInterface{
public void sleep();
}
tips: 接口之间只能继承,不能实现;抽象类中不一定含有抽象方法
- 迪米特原则
- 一个对象应该对其他对象保持最少的了解,又被称为最少知道原则
- 降低类之间的耦合度
- 强调只和朋友交流,不和陌生人说话
public interface Human{
}
public abstract class Programmer implements Human{
public abstract void work();
}
public class JavaProgrammer extends Programmer{
@Override
public void work(){
System.out.println("开发Java代码");
}
}
public class PythonProgrammer extends Programmer{
@Override
public void work(){
System.out.println("开发Python代码");
}
}
public interface Manager extends Human{
}
public class TeamLeader implements Manager{
private Programmer programmer;
public void setProgrammer(Programmer programmer){
this.programmer = programmer;
}
public void assignTasks(){
System.out.println("项目经理分配任务");
// 都有work方法实现,此处步骤多余,仅为方便阅读
if (programmer instanceof JavaProgrammer) {
((JavaProgrammer)programmer).work();
}
if (programmer instanceof PythonProgrammer) {
((PythonProgrammer)programmer).work();
}
}
}
public class Boss implements Manager{
public void meet(TeamLeader teamLeader){
System.out.println("老板开会,分布任务");
teamLeader.assignTasks();
}
}
- 里氏替换原则
- 是继承复用的基石,也是对开闭原则的补充
- 子类可以扩展父类的功能,但不能修改父类原有的功能
- 子类可以实现父类的抽象方法,但不能覆盖原有父类方法
- 子类可以增加自己的独有方法
- 本质是对子类的继承关系进行约束
- 合成复用原则
- 尽量使用对象组合、聚合的方式,而不是使用继承关系达到软件复用
- 可以使当前系统更加灵活,降低类之间耦合度
public class Teacher{
public void call() {
System.out.println("告知学生开家长会");
}
}
public class Student{
public void notify() {
System.out.println("通知家长开家长会");
}
}
public class Parent{
public void go() {
System.out.println("去开家长会");
}
}
这个案例,达到了一个“老师通知开家长会 -> 学生告知家长 -> 家长去开家长会”这样一个简单效果,但是并没有合成复用原则的应用。
public interface Notify{
public void notify();
}
public class WxCall implements Notify{
private Parent parent;
public void setParent(Parent parent){
this.parent = parent;
}
@Override
public void notify(){
System.out.println("微信通知家长");
parent.go();
}
}
public class PhoneCall implements Notify{
private Parent parent;
public void setParent(Parent parent){
this.parent = parent;
}
@Override
public void notify(){
System.out.println("电话通知家长");
parent.go();
}
}
public class Teacher{
private Notify notify;
public void setNotify(Notify notify) {
this.notify = notify;
}
public void call() {
System.out.println("告知学生开家长会");
// 告知家长
notify.notify();
}
}
tips: 接口之间也有多态
以上,在Teacher类中注入Notify,在Notify中注入Parent,即合成复用原则,整个过程简化到只需要teacher.call()
就实现了。
总结
开闭原则讲的是对可复用的对象使用抽象类、抽象方法提取;依赖倒转原则在此基础上要求对“规范”使用接口定义(接口可多实现),使用抽象方法定义规范;单一原则、接口隔离原则、迪米特原则都是为了降低类之间耦合度,要求程序员所定义的接口、类、方法尽量细化,功能单一;里氏替换原则对子类的继承关系进行了约束;合成复用原则提供了一种推荐写法使得代码更加简洁。