设计模式中的七个基本原则是:单一职责原则(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. 单一职责原则(SRP)
定义:一个类应该只有一个引起它变化的原因。换句话说,一个类应该只负责一项职责。
案例:
假设我们有一个Employee
类,它负责管理员工的个人信息和计算工资。根据SRP,我们应该将这两个职责分开,因为它们可能会独立变化。
// 违反SRP的例子
class Employee {
void save() {
// 保存员工信息
}
double calculateSalary() {
// 计算工资
return 0.0;
}
}
// 符合SRP的例子
class Employee {
void save() {
// 保存员工信息
}
}
class SalaryCalculator {
double calculateSalary(Employee employee) {
// 计算工资
return 0.0;
}
}
2. 开放封闭原则(OCP)
定义:软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。
案例: 假设我们有一个图形绘制程序,需要支持多种图形(如圆形、矩形)。我们可以通过抽象基类和子类来实现OCP。
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() {
// 绘制圆形
}
}
class Rectangle extends Shape {
void draw() {
// 绘制矩形
}
}
class ShapeDrawer {
void drawShape(Shape shape) {
shape.draw();
}
}
3. 里氏替换原则(LSP)
案例:
假设我们有一个Bird
类和一个Owl
类(猫头鹰)。Owl
类应该能够替换Bird
类而不破坏程序的逻辑。
class Bird {
void fly() {
// 飞行
}
}
class Owl extends Bird {
void fly() {
// 猫头鹰飞行
}
}
class BirdWatcher {
void watchBird(Bird bird) {
bird.fly();
}
}
4. 接口隔离原则(ISP)
定义:客户端不应该依赖它不需要的接口。换句话说,一个类不应该被迫实现它不需要的方法。
案例:
假设我们有一个Worker
接口,包含work()
和eat()
方法。Robot
类只需要实现work()
方法,但被迫实现eat()
方法。
// 违反ISP的例子
interface Worker {
void work();
void eat();
}
class Robot implements Worker {
public void work() {
// 工作
}
public void eat() {
// 机器人不需要吃饭
}
}
// 符合ISP的例子
interface Workable {
void work();
}
interface Eatable {
void eat();
}
class Robot implements Workable {
public void work() {
// 工作
}
}
class Human implements Workable, Eatable {
public void work() {
// 工作
}
public void eat() {
// 吃饭
}
}
5. 依赖倒置原则(DIP)
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
案例:
假设我们有一个Button
类和一个Light
类。Button
类不应该直接依赖Light
类,而是依赖一个抽象接口。
interface Switchable {
void turnOn();
void turnOff();
}
class Light implements Switchable {
public void turnOn() {
// 开灯
}
public void turnOff() {
// 关灯
}
}
class Button {
private Switchable device;
Button(Switchable device) {
this.device = device;
}
void press() {
if (device.isOn()) {
device.turnOff();
} else {
device.turnOn();
}
}
}
6. 迪米特法则(LoD)
定义:一个对象应该对其他对象有尽可能少的了解,即一个类应该对自己需要耦合或调用的类知道得最少。
案例:
假设我们有一个Order
类和一个Customer
类。Order
类不应该直接访问Customer
类的内部状态。
class Customer {
private String name;
String getName() {
return name;
}
}
class Order {
private Customer customer;
Order(Customer customer) {
this.customer = customer;
}
void printCustomerName() {
System.out.println(customer.getName());
}
}
7. 合成复用原则(CRP)
案例:
假设我们有一个Car
类和一个Engine
类。Car
类应该通过组合Engine
类来复用其功能,而不是通过继承。
class Engine {
void start() {
// 启动引擎
}
}
class Car {
private Engine engine;
Car(Engine engine) {
this.engine = engine;
}
void start() {
engine.start();
}
}