六大设计原则
- 单一职责原则
- 接口隔离原则
- 开闭原则
- 依赖倒置原则
- 里氏代换原则
- 迪米特法则
单一职责原则
我们分别看两个案例,一个是遵守单一职责原则,另一个是违背。
违背的案例
class Computer {
void calc() {
System.out.println("计算数据"); // 基本功能,么得问题
}
void display() {
System.out.println("显示计算结果"); // 现在的计算机确实有显示功能
}
void run() {
System.out.println("以百米冲刺的速度奔跑"); // 这什么玩意儿?这个类到底是干嘛的
}
}
遵守的案例
class Computer {
void calc() {
System.out.println("计算数据"); // 基本功能,么得问题
}
void display() {
System.out.println("显示计算结果"); // 现在的计算机确实有显示功能
}
}
class Humam {
void run() {
System.out.println("以百米冲刺的速度奔跑"); // 人会跑不是很正常嘛
}
}
单一职责的核心:限制类的职责范围,杜绝功能复杂的类的产生。
接口隔离原则也是同样的思想,就不废话了。
开闭原则
class Style {
public void set() {
System.out.println("设置圆角");
}
}
当需要改变样式的时候。不遵守开闭原则的做法。
class Style {
public void set() {
// System.out.println("设置圆角");
System.out.println("设置order");
/*
直接修改原有的方法上做修改
*/
}
}
而遵守开闭原则的做法。
// 将原有的Style类抽象成接口,这样对客户端也没有影响,
// 因为用的还是Style并没有改名,只是原来是个类,现在变成了接口
interface Style {
void set();
}
class Radius implements Style {
public void set() {
System.out.println("设置圆角");
}
}
class Order implements Style { // 不对原有的实现类修改,而是增加一个新个实现类
public void set() {
System.out.println("设置order");
}
}
开闭原则的核心:对修改关闭,对拓展开放。
不在原有的代码上增减新的代码,而是添加新的模块。核心要点是面向接口编程。
依赖倒置原则
不符合依赖倒置原则的案例。
class Radius {
public void set() {
System.out.println("设置圆角");
}
}
class Order {
public void set() {
System.out.println("设置order");
}
}
class Client {
public void setRadius(Radius radius) {
adius.set();
}
public void setOrder(Order order) {
rder.set();
}
}
符合依赖倒置原则的案例。
interface Style {
void set();
}
class Radius implements Style {
public void set() {
System.out.println("设置圆角");
}
}
class Order implements Style {
public void set() {
System.out.println("设置order");
}
}
class Client {
public void setStyle(Style style) {
style.set();
}
}
依赖倒置的核心:从依赖具体类变为依赖抽象或接口。面向接口编程。
里氏代换原则
不符合里氏代换原则的案例。
class CacheCard {
protected int balance;
public void peek() {
System.out.println("余额:" + balance);
}
public void deposit(int num) {
balance += num;
System.out.println("存款金额:" + num);
peek();
}
public void withdraw(int num) {
balance += num;
System.out.println("取款金额:" + num);
peek();
}
}
class CreditCard extends CacheCard {
public void deposit(int num) { // 信用卡并没有存钱这个功能,不应该重写
balance += num;
System.out.println("还款金额:" + num);
peek();
}
public void withdraw(int num) { // 也没有取款的功能,不应该重写
balance += num;
System.out.println("支付金额:" + num);
peek();
}
}
符合里氏代换原则的案例。
interface BankCard {
int balance;
default void peek() {
System.out.println("余额:" + balance);
}
void positive(int num);
void negative(int num);
}
class CacheCard implements BankCard {
public void positive(int num) {
balance += num;
System.out.println("存款金额:" + num);
peek();
}
public void negative(int num) {
balance -= num;
System.out.println("取款金额:" + num);
peek();
}
}
class CreditCard implements BankCard {
public void positive(int num) {
balance += num;
System.out.println("还款金额:" + num);
peek();
}
public void negative(int num) {
balance -= num;
System.out.println("支付金额:" + num);
peek();
}
}
里氏代换原则的核心思想:使用父类能够实现的功能,使用其子类依旧能实现。限制方法重写的范围,从业务的角度出发我们只可以重写父类中被允许重写的方法,而不是从Java语法角度(那能重写的多了去了)出发重写方法。
迪米特法则
不符合迪米特法则的案例。
class Student {
String name;
String sex;
int score;
}
class Teacher {
String name;
String sex;
Student[] students;
int max() {
int res = 0;
for (student : students) {
res = Math.max(res, student.score);
}
return res;
}
int min() {
int res = 0;
for (student : students) {
res = Math.min(res, student.score);
}
return res;
}
}
class President {
String name;
String sex;
Student[] students; // 不应该依赖Student类,而应该依赖Teacher类,将所有对于students的操作封装到Teacher类中
Teacher[] teachers;
int avg() { // 这个方法应该在Teacher中定义
int res = 0;
for (student : students) {
res += student.score;
}
return res / students.length;
}
String[] teachersName() { // 获取所有的老师名字
String[] res = new String[teachers.length];
for (int i = 0; i < res.length; i ++) {
res[i] = teachers[i].name;
}
return res;
}
}
符合迪米特法则的案例。
class Student {
String name;
String sex;
int score;
}
class Teacher {
String name;
String sex;
Student[] students;
int max() {
int res = 0;
for (student : students) {
res = Math.max(res, student.score);
}
return res;
}
int min() {
int res = 0;
for (student : students) {
res = Math.min(res, student.score);
}
return res;
}
int avg() { // 这个方法应该在Teacher中定义
int res = 0;
for (student : students) {
res += student.score;
}
return res / students.length;
}
}
class President {
String name;
String sex;
Teacher[] teacher; // 依赖Teacher类
int[] avgs() { // 获取每个班级的平均分
int[] res = new int[teacher.length];
for (int i = 0; i < res.length; i ++) {
res[i] = teacher[i].avg(); // 实际计算调用Teacher内的计算
}
return res;
}
String[] teachersName() { // 获取所有的老师名字
String[] res = new String[teachers.length];
for (int i = 0; i < res.length; i ++) {
res[i] = teachers[i].name;
}
return res;
}
}
迪米特法则的核心思想:最少知道,最少依赖。类的定义应当把对于其他类的依赖降到最低。
遵守迪米特法则的同时也基本满足了单一职责原则。