返回

设计模式六大原则:白话理解与实战应用

IOS

设计模式是一组可重复使用的解决方案,用于解决软件开发中常见的特定问题。理解设计模式的原则至关重要,它可以帮助我们构建灵活、可维护且可扩展的系统。本文将用一种白话的方式解释设计模式的六大原则,并提供实际示例来说明它们如何应用于现实世界的场景。

单一职责原则(SRP)

SRP 规定每个模块或类应该只负责一项特定职责。避免将多个职责组合到一个类中,这有助于提高代码的可读性、可维护性和可测试性。

示例:

// 违反 SRP
class UserService {
  public createUser(user: User): void;
  public updateUser(user: User): void;
  public deleteUser(userId: string): void;
  public getUser(userId: string): User | null;
}

// 遵循 SRP
class UserCreator {
  public createUser(user: User): void;
}

class UserUpdater {
  public updateUser(user: User): void;
}

class UserDeleter {
  public deleteUser(userId: string): void;
}

class UserGetter {
  public getUser(userId: string): User | null;
}

开放封闭原则(OCP)

OCP 规定软件应该对扩展开放,对修改关闭。这意味着我们应该能够在不修改现有代码的情况下向系统添加新功能。

示例:

// 违反 OCP
class Shape {
  public draw(): void;
}

class Rectangle: Shape {
  public draw(): void {
    // Draw a rectangle
  }
}

class Circle: Shape {
  public draw(): void {
    // Draw a circle
  }
}

// 遵循 OCP
interface Shape {
  public draw(): void;
}

class Rectangle implements Shape {
  public draw(): void {
    // Draw a rectangle
  }
}

class Circle implements Shape {
  public draw(): void {
    // Draw a circle
  }
}

class Triangle implements Shape {
  public draw(): void {
    // Draw a triangle
  }
}

里氏代换原则(LSP)

LSP 规定子类对象应该能够替换其父类对象,而不需要修改客户端代码。这意味着子类应该遵循父类的行为,但可以提供额外的功能。

示例:

// 违反 LSP
class Animal {
  public makeSound(): void;
}

class Dog: Animal {
  public makeSound(): void {
    // Bark
  }
}

class Cat: Animal {
  public makeSound(): void {
    // Meow
  }
  
  public climbTree(): void {
    // Cats can climb trees
  }
}

// 遵循 LSP
interface Animal {
  public makeSound(): void;
}

class Dog implements Animal {
  public makeSound(): void {
    // Bark
  }
}

class Cat implements Animal {
  public makeSound(): void {
    // Meow
  }
}

// Client code
Animal animal = new Cat();
animal.makeSound(); // Meow

依赖倒置原则(DIP)

DIP 规定高层模块不应该依赖于低层模块,而是应该依赖于抽象或接口。这有助于解耦系统并提高其可测试性。

示例:

// 违反 DIP
class UserService {
  private userRepository: UserRepository;
  
  public createUser(user: User): void {
    this.userRepository.save(user);
  }
}

// 遵循 DIP
interface UserRepository {
  public save(user: User): void;
}

class UserService {
  private userRepository: UserRepository;
  
  public createUser(user: User): void {
    this.userRepository.save(user);
  }
}

接口隔离原则(ISP)

ISP 规定接口应该只包含客户端需要的特定方法。避免创建庞大的接口,这将迫使客户端实现它们不需要的方法。

示例:

// 违反 ISP
interface IShape {
  public draw();
  public resize();
  public rotate();
}

// 遵循 ISP
interface IDrawable {
  public draw();
}

interface IResizable {
  public resize();
}

interface IRotatable {
  public rotate();
}

合成复用原则(CRP)

CRP 规定优先使用组合而非继承。这意味着我们应该通过组合对象来创建新的功能,而不是创建新的子类。

示例:

// 违反 CRP
class Bird extends Animal {
  public fly(): void;
}

class Fish extends Animal {
  public swim(): void;
}

// 遵循 CRP
class Bird {
  private flyingAbility: IFlyingAbility;
  
  public fly(): void {
    this.flyingAbility.fly();
  }
}

class Fish {
  private swimmingAbility: ISwimmingAbility;
  
  public swim(): void {
    this.swimmingAbility.swim();
  }
}

interface IFlyingAbility {
  public fly(): void;
}

interface ISwimmingAbility {
  public swim(): void;
}