写在最前
文档地址: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 {@Overridepublic void eat() {System.out.println("Java程序员在吃饭");} @Overridepublic void sleep() {System.out.println("Java程序员在睡觉");} @Overridevoid 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 {@Overridepublic void eat() {System.out.println("学生在吃饭");} @Overridepublic void sleep() {System.out.println("学生在睡觉");} public void study() {System.out.println("学生在学习");} }
3.增加高中生
满足开闭原则,增加高中生,但不修改学生类。
public class HighSchoolStudent extends Student {@Overridepublic void eat() {System.out.println("高中生在吃饭");} @Overridepublic void sleep() {System.out.println("高中生在睡觉");} @Overridepublic 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 {@Overridevoid 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 {@Overridepublic void eat() {System.out.println("学生在吃饭");} @Overridepublic 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 { @Overridepublic void eat() {System.out.println("程序员在吃饭");} @Overridepublic void sleep() {System.out.println("程序员在睡觉");} /*** 程序员都需要工作*/abstract void work(); }
定义Java程序员、测试程序员
Java程序员
public class JavaProgrammer extends Programmer {@Overridepublic void eat() {System.out.println("Java程序员在吃饭");} @Overridepublic void sleep() {System.out.println("Java程序员在睡觉");} @Overridevoid work() {System.out.println("Java程序员在工作");} }
测试程序员
public class TestProgrammer extends Programmer {@Overridepublic void eat() {System.out.println("测试程序员在吃饭");} @Overridepublic void sleep() {System.out.println("测试程序员在睡觉");} @Overridevoid 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 { @Overridevoid 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();} }