设计模式的七大原则
1. 开闭原则( Open Close Principle )
定义:软件实体(类、模块、函数)应该对扩展开放,对修改关闭。
解释:当需要改变某些功能时,通过增加新代码(扩展),而不是修改现有代码,来保持系统的稳定性。
- 对扩展开放,对修改关闭
- 使用抽象进行构建,使用实现扩展细节
- 面向抽象编程
- 提高系统的可复用性和可维护性
// 不遵循开闭原则
class Notification {
public void send(String type) {
if (type.equals("EMAIL")) {
System.out.println("Sending Email...");
} else if (type.equals("SMS")) {
System.out.println("Sending SMS...");
}
}
}
// 遵循开闭原则
interface Notification {
void send();
}
class EmailNotification implements Notification {
public void send() {
System.out.println("Sending Email...");
}
}
class SmsNotification implements Notification {
public void send() {
System.out.println("Sending SMS...");
}
}
2. 依赖倒转原则( Dependence Inversion Principle )
定义:高层模块不应该依赖低层模块,二者都应该依赖抽象;抽象不应该依赖具体实现,具体实现应该依赖抽象。
解释:通过接口或抽象类实现解耦,提升代码的灵活性和稳定性。
- 依赖倒转原则是开闭原则的基础,针对接口进行编程
- 依赖抽象,而不是具体实现
- 可以减少类之间的耦合性,提高系统稳定性,提高代码可读性和可维护性
- 降低修改程序所造成的风险
// 不遵循依赖倒置原则
class Keyboard {
}
class Computer {
private Keyboard keyboard;
public Computer() {
this.keyboard = new Keyboard();
}
}
// 遵循依赖倒置原则
interface InputDevice {
}
class Keyboard implements InputDevice {
}
class Computer {
private InputDevice inputDevice;
public Computer(InputDevice inputDevice) {
this.inputDevice = inputDevice;
}
}
3. 单一职责原则( Single Responsibility Principle )
定义:每个类只负责一项职责,即一个类只有一个引起它变化的原因。
解释:将职责明确分离,避免一个类承担过多的职责,从而降低耦合性,提高代码可读性和维护性。
- 一个类、接口、方法,只负责一项职责
- 降低程序的复杂度,提高程序的可维护性,降低变更带来的风险
// 不遵循单一职责原则
class UserManager {
public void addUser(String user) {
System.out.println("User added: " + user);
}
public void sendEmail(String user) {
System.out.println("Email sent to: " + user);
}
}
// 遵循单一职责原则
class UserService {
public void addUser(String user) {
System.out.println("User added: " + user);
}
}
class EmailService {
public void sendEmail(String user) {
System.out.println("Email sent to: " + user);
}
}
4. 接口隔离原则( Interface Segregation Principle )
定义:一个类不应该依赖它不使用的接口,接口应保持精简。
解释:将臃肿的接口拆分成多个小接口,每个接口只包含相关的方法,避免不必要的依赖。
- 用多个接口,而不是使用单一的接口
- 尽量细化接口,接口中的方法尽量少
- 符合低耦合的设计思想,提高了可扩展性和可维护性
// 不遵循接口隔离原则
interface Animal {
void fly();
void run();
void swim();
}
class Dog implements Animal {
@Override
public void fly() {
throw new UnsupportedOperationException("Dogs can't fly");
}
@Override
public void run() {
System.out.println("Dog is running");
}
@Override
public void swim() {
System.out.println("Dog is swimming");
}
}
// 遵循接口隔离原则
interface CanRun {
void run();
}
interface CanSwim {
void swim();
}
class Dog implements CanRun, CanSwim {
@Override
public void run() {
System.out.println("Dog is running");
}
@Override
public void swim() {
System.out.println("Dog is swimming");
}
}
5. 迪米特法则(Law of Demeter)
定义:一个对象应该对其他对象有最少的了解。
解释:模块间只通过必要的接口进行通信,尽量减少类之间的直接依赖关系,降低系统的耦合度。
- 一个对象应该对其他对象保持最少的了解,又称最少知道原则(Least Knowledge Principle)
- 为了降低类与类之间的耦合关系
- 只和朋友交流,不和陌生人说话
- 友指的是成员变量或方法中输入或输出的参数
// 不遵循迪米特法则
class Engine {
public void start() {
System.out.println("Engine started");
}
}
class Car {
private Engine engine = new Engine();
public void start() {
engine.start();
}
}
// 遵循迪米特法则
class Engine {
public void start() {
System.out.println("Engine started");
}
}
class Car {
private Engine engine = new Engine();
public void start() {
engine.start();
}
}
6. 里氏替换原则( Liskov Substitution Principle )
定义:子类对象必须能够替换父类对象,并且程序行为保持一致。
解释:子类应继承父类的所有行为规范,但不能违背父类的预期功能,保证多态性不会被破坏。
- 里氏替换原则是继承复用的基石,对开闭原则的补充
- 子类可以扩展父类的功能,但是不能修改父类原有的功能
- 子类可以实现父类的抽象方法,但是不能覆盖原有父类的方法
- 子类中可以增加自己特有的方法
- 对子类的继承关系进行约束,开闭原则的补充
- 可以增加程序的健壮性
// 不遵循里氏替换原则
class Bird {
public void fly() {
System.out.println("Bird is flying");
}
}
class Penguin extends Bird {
@Override
public void fly() {
throw new UnsupportedOperationException("Penguins can't fly!");
}
}
// 遵循里氏替换原则
abstract class Bird {
public abstract void move();
}
class FlyingBird extends Bird {
@Override
public void move() {
System.out.println("Bird is flying");
}
}
class Penguin extends Bird {
@Override
public void move() {
System.out.println("Penguin is walking");
}
}
7. 合成复用原则( Composite Reuse Principle )
定义:优先使用组合(或聚合)而不是继承来实现代码复用。
解释:通过组合的方式将功能模块化,避免因为继承带来的强耦合和灵活性不足的问题。
- 尽量使用对象组合,聚合的方式,而不是使用继承关系达到软件复用的目的
- 可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响
// 不遵循合成复用原则
class Engine {
public void start() {
System.out.println("Engine started");
}
}
class GasCar extends Engine {
}
class ElectricCar extends Engine {
}
// 遵循合成复用原则
class Engine {
public void start() {
System.out.println("Engine started");
}
}
class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}