Java设计模式的六大原则
单一职责原则(Single Responsibility Principle,SRP):一个类只负责一项职责。如果一个类承担了多个职责,那么在修改其中一个职责的时候,可能会影响其他职责的正常运行。
代码示例:
// bad design
public class Car {
public void move() {
// do something
}
public void clean() {
// do something
}
public void repair() {
// do something
}
}
// good design
public class Car {
public void move() {
// do something
}
}
public class CarCleaner {
public void clean(Car car) {
// do something
}
}
public class CarMechanic {
public void repair(Car car) {
// do something
}
}
开闭原则(Open-Closed Principle,OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。也就是说,在修改已有代码的情况下,尽量不要修改原有的代码,而是通过扩展来实现功能的增加。
代码示例:
// bad design
public class Car {
public void move() {
// do something
}
public void moveFast() {
// do something
}
}
// good design
public interface Car {
void move();
}
public class NormalCar implements Car {
public void move() {
// do something
}
}
public class SportsCar implements Car {
public void move() {
// do something faster
}
}
里氏替换原则(Liskov Substitution Principle,LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。简单来说,子类可以替换掉父类,并且程序仍然能够正确地执行。
代码示例:
// bad design
public class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
public class Square extends Rectangle {
@Override
public void setWidth(int width) {
this.width = width;
this.height = width;
}
@Override
public void setHeight(int height) {
this.width = height;
this.height = height;
}
}
// good design
public interface Shape {
int getArea();
}
public class Rectangle implements Shape {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public int getArea() {
return width * height;
}
}
public class Square implements Shape {
private int side;
public Square(int side) {
this.side = side;
}
@Override
public int getArea() {
return side * side;
}
}
接口隔离原则(Interface Segregation Principle,ISP):客户端不应该依赖于它不需要的接口。一个类不应该强迫其它的类依赖它们不需要使用的接口。
代码示例:
// bad design
public interface Vehicle {
void move();
void clean();
void repair();
}
public class Car implements Vehicle {
@Override
public void move() {
// do something
}
@Override
public void clean() {
// do something
}
@Override
public void repair() {
// do something
}
}
// good design
public interface Vehicle {
void move();
}
public interface Cleanable {
void clean();
}
public interface Repairable {
void repair();
}
public class Car implements Vehicle, Cleanable, Repairable {
@Override
public void move() {
// do something
}
@Override
public void clean() {
// do something
}
@Override
public void repair() {
// do something
}
}
依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖于底层模块,二者都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
代码示例:
// bad design
public class Car {
public void startGasolineEngine() {
// start the gasoline engine
}
}
public class CarOwner {
private Car car = new Car();
public void moveCar() {
car.startGasolineEngine();
}
}
// good design
public interface Engine {
void start();
}
public class GasolineEngine implements Engine {
@Override
public void start() {
// start the gasoline engine
}
}
public class ElectricEngine implements Engine {
@Override
public void start() {
// start the electric engine
}
}
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void move() {
engine.start();
}
}
public class CarOwner {
private Car car = new Car(new GasolineEngine());
public void moveCar() {
car.move();
}
}
迪米特法则(Law of Demeter,LoD):一个对象应该对其他对象有尽可能少的了解,不和陌生人说话。也就是说,一个对象应该尽量减少对其它对象的依赖和交互,只依赖于那些真正需要交互的对象。
代码示例:
// bad design
public class CarOwner {
public void cleanCar(Car car) {
car.clean();
}
}
// good design
public class Car {
public void clean() {
// do something
}
}
public class CarCleaner {
public void clean(Car car) {
car.clean();
}
}
public class CarOwner {
private CarCleaner cleaner;
public CarOwner(CarCleaner cleaner) {
this.cleaner = cleaner;
}
public void cleanCar(Car car) {
cleaner.clean(car);
}
}
解惑,第七大设计模式》
也有人会将"合成复用原则"(Composition/Aggregation Reuse Principle,CARP)视为Java设计模式的第七大原则,但它其实是“里氏替换原则”和“开闭原则”的延伸和具体化。该原则主要强调使用对象组合(composition)和聚合(aggregation)来实现代码重用,而不是通过继承来实现。通过组合和聚合,一个对象可以在运行时动态地获取其所需的功能,而不需要静态地继承父类的行为。因此,CARP 可以看作是“开闭原则”和“里氏替换原则”的具体实践。