写在最前
文档地址:Wiki - Gitee.com
设计模式
推荐浏览:软件设计模式
代表了代码的最佳实践,被有经验的开发人员所使用;
设计模式是很多被反复使用并知晓的,主要是对代码和经验的总结;
使用设计模式是为了重用代码,让代码更容易被他人理解,保证代码的可靠性;
对接口编程而不是对实现变成;
有限使用对象组合而不是继承关系;
设计原则
设计模式的六大设计(第七点为后增)原则通常是指的面向对象设计原则,也被称为SOLID原则。这六大设计原则分别是:
单一职责原则(Single Responsibility Principle,SRP):
一个类应该只有一个引起变化的原因。这意味着一个类应该只有一个责任,只关注一个功能领域;
降低程序的复杂度,提高程序可维护性,降低了变更所带来的风险;
开放/封闭原则(Open/Closed Principle,OCP):
软件实体(类、模块、函数等)应该是可扩展的,但不可修改的。即,对于新增功能应通过扩展而不是修改现有代码来实现;
使用抽象进行构建,使用实现扩展细节,面向抽象编程;
提高软件系统的可复用性和可维护性;
里氏替换原则(Liskov Substitution Principle,LSP):
所有引用基类的地方必须能够透明地使用其子类的对象,即子类可以替代基类而不影响程序的正确性;
里氏替换原则是继承复用的基石,对开闭原则的补充;
子类可以实现父类的抽象方法,但是不能覆盖原有父类的方法,子类中可以增加自己特有的方法;
可以增加程序的健壮性;
接口隔离原则(Interface Segregation Principle,ISP):
一个类对于它的客户端应该只暴露它们需要的方法,而不应该强迫客户端使用它们不需要的方法。接口应该是客户端特定的,而不是通用的;
尽量细化接口,接口中的方法尽量少;
符合低耦合的设计思想,提高了可扩展性和可维护性;
依赖倒置原则(Dependency Inversion Principle,DIP):
高层模块不应该依赖于低层模块,而是两者都应该依赖于抽象。抽象不应该依赖于具体实现,而具体实现应该依赖于抽象;
依赖倒置原则是开闭原则的基础,针对接口进行编程;
可以减少类之间的耦合行,提高系统稳定性,提高代码可读性和可维护性;
降低修改程序所造成的风险;
迪米特法则(Law of Demeter,LoD):
一个对象应该对其他对象有最少的了解,即一个对象不应该直接调用另一个对象内部的方法,而应该通过一些中介者来进行间接调用;
为了降低类与类之间的耦合关系;
强调只和朋友交流,不和陌生人说话。朋友指的是成员变量或方法中输入输出的参数;
合成复用原则(Composite Reuse Principle,CRP):
尽量使用对象组合,聚合的方式,而不是使用继承关系达到软件复用的目的;
可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少;
这些设计原则共同为面向对象设计提供了指导方针,有助于创建更灵活、可维护和可扩展的代码。在应用这些原则时,设计模式通常被用来实现这些原则的具体设计方案。
单一职责原则
1.定义人类接口
人类都具有吃饭、睡觉的行为
public interface Human { /** * 吃饭 */ void eat(); /** * 睡觉 */ void sleep(); }
2.定义程序员抽象类
程序员都需要工作
public abstract class Programmer implements Human { /** * 程序员都需要工作 */ abstract void work(); }
3.Java程序员
具备Java编写能力
public class JavaProgrammer extends Programmer { @Override public void eat() { System.out.println("Java程序员在吃饭"); } @Override public void sleep() { System.out.println("Java程序员在睡觉"); } @Override void work() { System.out.println("Java程序员在工作"); } /** * Java程序员其他行为 */ void codeJava() { System.out.println("Java程序员在写Java代码"); } }
4.测试
public class Test { public static void main(String[] args) { JavaProgrammer javaProgrammer = new JavaProgrammer(); javaProgrammer.codeJava(); javaProgrammer.eat(); javaProgrammer.work(); javaProgrammer.sleep(); } }
开放/封闭原则
1.定义人类接口
人类都具有吃饭、睡觉的行为
public interface Human { /** * 吃饭 */ void eat(); /** * 睡觉 */ void sleep(); }
2.学生实现人类接口
学生都具有学习的行为
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("学生在学习"); } }
3.增加高中生
满足开闭原则,增加高中生,但不修改学生类。
public class HighSchoolStudent extends Student { @Override public void eat() { System.out.println("高中生在吃饭"); } @Override public void sleep() { System.out.println("高中生在睡觉"); } @Override public void study() { System.out.println("高中生在学习"); } /** * 扩展高中生独有的属性或行为 */ public void doSomeThing() { System.out.println("高中生在谈恋爱"); } }
4.测试
public class Test { public static void main(String[] args) { Student student = new Student(); student.eat(); student.sleep(); student.study(); // 不修改学生类(对修改关闭),增加高中生(对扩展开发) HighSchoolStudent highSchoolStudent = new HighSchoolStudent(); highSchoolStudent.eat(); highSchoolStudent.sleep(); highSchoolStudent.study(); highSchoolStudent.doSomeThing(); } }
里氏替换原则
1.定义老鼠类
public class Mouse { void burrow() { System.out.println("老鼠会打洞。。。"); } }
2.定义仓鼠类继承老鼠
public class Hamster extends Mouse { // 子类可以不修改父类的方法,只是继承并使用 (老鼠天生会打洞) }
3.定义玩具鼠类继承老鼠
public class ToyMouse extends Mouse { @Override void burrow() { // 它可以覆盖 burrow 方法,但不应该修改已经存在的行为 System.out.println("我是玩具鼠,我不会打洞,我会上天"); } }
4.测试
public class Test { public static void main(String[] args) { Hamster hamster = new Hamster(); // 老鼠生的会打洞 hamster.burrow(); ToyMouse toyMouse = new ToyMouse(); // 老鼠生的不会打洞,会上天,就违背了该原则 toyMouse.burrow(); } }
接口隔离原则
1.定义人类接口
public interface Human {}
2.人类行为拆分接口,进行接口隔离
吃饭
public interface EatAction extends Human { void eat(); }
睡觉
public interface SleepAction extends Human { void sleep(); }
3.学生具备吃饭、睡觉的行为
public class Student implements EatAction, SleepAction { @Override public void eat() { System.out.println("学生在吃饭"); } @Override public void sleep() { System.out.println("学生在睡觉"); } }
4.测试
public class Test { public static void main(String[] args) { Student student = new Student(); student.eat(); student.sleep(); } }
依赖倒置原则
1.定义人类接口
人类都具有吃饭、睡觉的行为
public interface Human { /** * 吃饭 */ void eat(); /** * 睡觉 */ void sleep(); }
2.定义程序员抽象类
public abstract class Programmer implements Human { @Override public void eat() { System.out.println("程序员在吃饭"); } @Override public void sleep() { System.out.println("程序员在睡觉"); } /** * 程序员都需要工作 */ abstract void work(); }
定义Java程序员、测试程序员
Java程序员
public class JavaProgrammer extends Programmer { @Override public void eat() { System.out.println("Java程序员在吃饭"); } @Override public void sleep() { System.out.println("Java程序员在睡觉"); } @Override void work() { System.out.println("Java程序员在工作"); } }
测试程序员
public class TestProgrammer extends Programmer { @Override public void eat() { System.out.println("测试程序员在吃饭"); } @Override public void sleep() { System.out.println("测试程序员在睡觉"); } @Override void work() { System.out.println("测试程序员在工作"); } }
4.测试
public class Test { public static void main(String[] args) { JavaProgrammer javaProgrammer = new JavaProgrammer(); javaProgrammer.eat(); javaProgrammer.work(); javaProgrammer.sleep(); TestProgrammer testProgrammer = new TestProgrammer(); testProgrammer.work(); } }
迪米特法则
1.定义人类接口
public interface Human {}
2.定义管理层接口并实现
public interface Manager extends Human {}
公司老板
public class Boss implements Manager { public void meet(TeamLeader teamLeader) { System.out.println("老板开会,发布任务"); teamLeader.assignTasks(); } }
团队领导
public class TeamLeader implements Manager { private Programmer programmer; public void setProgrammer(Programmer programmer) { this.programmer = programmer; } public void assignTasks() { System.out.println("团队领导给研发分配任务"); this.programmer.work(); } }
3.定义程序员接口并实现
public abstract class Programmer implements Human { /** * 程序员都需要工作 */ abstract void work(); }
Java程序员
public class JavaProgrammer extends Programmer { @Override void work() { System.out.println("Java程序员完成Java代码开发"); } }
4.测试
public class Test { public static void main(String[] args) { // 老板准备发布任务 Boss boss = new Boss(); // 找到项目经理 TeamLeader teamLeader = new TeamLeader(); // 项目经理拉上手底下研发 JavaProgrammer javaProgrammer = new JavaProgrammer(); teamLeader.setProgrammer(javaProgrammer); // 老板发布任务 boss.meet(teamLeader); } }
合成复用原则
1.定义汽车引擎
public class Engine { void start() { System.out.println("发动机正在启动"); } }
2.定义汽车
public class Car { private Engine engine; Car(Engine engine) { this.engine = engine; } void start() { engine.start(); System.out.println("汽车正在启动"); } }
3.测试
public class Test { public static void main(String[] args) { // 在传统的继承方式下,可能会让Car继承自Engine,但这样的设计可能导致不必要的耦合,违反了合成复用原则。 Engine engine = new Engine(); // 使用合成复用原则通过组合来实现复用。 Car car = new Car(engine); car.start(); } }