一、依赖倒转原则
定义
高层模块不应该依赖低层模块,两者都应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象,简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
例子
import lombok.Data;
@Data
public class Computer {
private HardDisk hardDisk;
private Cpu cpu;
private Memory memory;
void run(){
System.out.println("运行计算机");
String data = hardDisk.get();
System.out.println("从硬盘上读取的数据是:" + data);
cpu.run();
memory.save();
}
}
public interface Cpu {
public void run();
}
public interface HardDisk {
public String get();
}
public class IntelCpu implements Cpu{
@Override
public void run() {
System.out.println("使用Intel处理器");
}
}
public class KingstonMemory implements Memory{
@Override
public void save() {
System.out.println("使用金士顿内存条");
}
}
public interface Memory {
public void save();
}
public class xijieHardDisk implements HardDisk{
@Override
public String get() {
return "数据";
}
}
public class Test {
public static void main(String[] args) {
xijieHardDisk xijieHardDisk = new xijieHardDisk();
IntelCpu intelCpu = new IntelCpu();
KingstonMemory kingstonMemory = new KingstonMemory();
Computer computer = new Computer();
computer.setHardDisk(xijieHardDisk);
computer.setCpu(intelCpu);
computer.setMemory(kingstonMemory);
computer.run();
}
}
二、 合成复用原则
尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现,通常类的复用分为继承复用和合成复用,继承复用虽然有简单和易实现的优点,但是也存在以下缺点:
- 继承复用破坏了类的封装性,因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称白箱复用
- 子类与父类的耦合度高,父类的实现的任何改变都会导致子类的实现发生改变,这不利于类的扩展与维护
- 它限制了复用的灵活性,从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化
采用组合继承或聚合复用时,可以将现有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有的对象的功能,它有以下优点:
- 它维持了类的封装性,因为成分对象的内部细节是新对象看不见的,所以这种复用又称之为黑箱复用
- 对象间的耦合度低,可以在类的成员位置声明抽象
- 复用的灵活性高,这种复用可以在运行时动态进行,新对象可以动态的引用与成分对象类型相同的对象
三、开闭原则
对修改关闭,对扩展开放;在程序需要进行扩展的时候,不能去修改原代码,实现一个热插拔效果,简而言之,是为了使程序的扩展性好,易于维护和升级。
例子:
public abstract class AbstractSkin {
public abstract void display();
}
public class DefaultSkin extends AbstractSkin{
@Override
public void display() {
System.out.println("默认皮肤");
}
}
public class QqSkin extends AbstractSkin{
public void display() {
System.out.println("qq皮肤");
}
}
import lombok.Data;
@Data
public class SougouInput {
private AbstractSkin skin;
public void display(){
skin.display();
}
}
public class Test {
public static void main(String[] args) {
SougouInput sougouInput = new SougouInput();
DefaultSkin defaultSkin = new DefaultSkin();
sougouInput.setSkin(defaultSkin);
sougouInput.display();
System.out.println("--------");
QqSkin qqSkin = new QqSkin();
sougouInput.setSkin(qqSkin);
sougouInput.display();
}
}
四、 接口隔离原则
客户端不应该依赖于它不使用的方法,一个类对于另一个类的依赖应该建立在最小的接口上
例子:
public interface AntiTheft {
void antiTheft();
}
public interface Fireproof {
void fireproof();
}
public interface Waterproof {
void waterproof();
}
public class SafetyDoor implements AntiTheft, Fireproof, Waterproof{
@Override
public void fireproof() {
System.out.println("防火");
}
@Override
public void waterproof() {
System.out.println("防水");
}
@Override
public void antiTheft() {
System.out.println("防盗");
}
}
public class Test {
public static void main(String[] args) {
SafetyDoor safetyDoor = new SafetyDoor();
safetyDoor.antiTheft();
safetyDoor.fireproof();
safetyDoor.waterproof();
}
}
五、 迪米特法则
迪米特法则又叫最少知识原则,其含义是,如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用,其目的是降低类之间的耦合度,提高模块的相对独立性。
例子
@Data
@AllArgsConstructor
public class Star {
private String name;
}
@Data
@AllArgsConstructor
public class Fans {
private String name;
}
@Data
@AllArgsConstructor
public class Company {
private String name;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Agent {
private Star star;
private Fans fans;
private Company company;
public void meeting(){
System.out.println(star.getName() + "和粉丝" + fans.getName() + "见面");
}
public void business(){
System.out.println(star.getName() + "和经纪公司" + company.getName() + "洽谈");
}
}
public class Test {
public static void main(String[] args) {
Agent agent = new Agent();
Star star = new Star("肖战");
agent.setStar(star);
Fans fans = new Fans("张三");
agent.setFans(fans);
Company company = new Company("tw");
agent.setCompany(company);
agent.meeting();
agent.business();
}
}
六、里式代换原则
任何基类可以出现的地方,子类一定可以出现,通俗理解,子类可以扩展父类的功能,但是不能改变父类原有的功能,换句话,子类继承父类时,除添加新的方法完成新增功能之外,尽量不要重写父类的方法。
例子
public interface Quadrilateral {
double getLength();
double getWidth();
}
public class Rectangle implements Quadrilateral{
private Double with;
public Double length;
public void setWith(Double with) {
this.with = with;
}
public void setLength(Double length) {
this.length = length;
}
@Override
public double getLength() {
return length;
}
@Override
public double getWidth() {
return with;
}
}
public class Square implements Quadrilateral{
private double side;
public void setSide(double side) {
this.side = side;
}
@Override
public double getLength() {
return side;
}
@Override
public double getWidth() {
return side;
}
}
public class Test {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setLength(20.0);
rectangle.setWith(10.0);
resize(rectangle);
printLengthAndWidth(rectangle);
}
public static void resize(Rectangle rectangle){
while (rectangle.getWidth() <= rectangle.getLength()) {
rectangle.setWith(rectangle.getWidth() + 1);
}
}
public static void printLengthAndWidth(Quadrilateral quadrilateral) {
System.out.println(quadrilateral.getLength());
System.out.println(quadrilateral.getWidth());
}
}