设计模式原则

39 阅读2分钟

用一个简单的例子来说明这六大设计原则(以单一职责原则、开闭原则、里氏替换原则、接口隔离原则、依赖倒置原则、迪米特法则为例)。


🧱 场景:图书管理系统

我们有一个系统,可以展示书籍信息和根据用户类型推荐书籍。现在我们要设计一个类结构,让它符合这些设计原则。


✅ 1. 单一职责原则(SRP)

问题:如果一个类既负责显示书籍信息,又负责推荐书籍,那它就有两个职责。

解决

class BookDisplay {
    void showBookDetails(Book book) {
        // 显示书籍详情
    }
}

class BookRecommender {
    List<Book> recommendBooks(User user) {
        // 根据用户推荐书籍
    }
}

👉 每个类只做一件事,职责清晰。


✅ 2. 开闭原则(OCP)

问题:如果我们想增加一种新的推荐策略(比如按评分推荐),不应该去修改已有代码。

解决

interface RecommendationStrategy {
    List<Book> recommend(User user);
}

class PopularRecommendation implements RecommendationStrategy {
    public List<Book> recommend(User user) {
        // 推荐热门书籍
    }
}

class RatedRecommendation implements RecommendationStrategy {
    public List<Book> recommend(User user) {
        // 推荐高评分书籍
    }
}

👉 当新增策略时,只需扩展新类,不修改已有逻辑。


✅ 3. 里氏替换原则(LSP)

问题:子类不能破坏父类的行为。

解决

abstract class BookService {
    abstract void borrowBook(User user, Book book);
}

class RegularBookService extends BookService {
    void borrowBook(User user, Book book) {
        // 正常借书流程
    }
}

class ReferenceBookService extends BookService {
    void borrowBook(User user, Book book) {
        throw new UnsupportedOperationException("参考书不可外借");
    }
}

⚠️ 这样不符合 LSP,因为子类改变了父类行为。

✅ 正确做法是不要让 ReferenceBookService 继承 borrowBook() 方法,或者通过组合方式处理。


✅ 4. 接口隔离原则(ISP)

问题:如果一个接口定义了太多方法,客户端被迫实现不需要的方法。

解决

interface Borrowable {
    void borrow();
}

interface Readable {
    void readOnline();
}

class EBook implements Borrowable, Readable {
    public void borrow() { /* 可借阅 */ }
    public void readOnline() { /* 支持在线阅读 */ }
}

class PaperBook implements Borrowable {
    public void borrow() { /* 可借阅 */ }
}

👉 客户端只依赖自己需要的接口。


✅ 5. 依赖倒置原则(DIP)

问题:高层模块(如推荐器)不应直接依赖低层模块(如数据库操作)。

解决

interface BookRepository {
    List<Book> findAll();
}

class DatabaseBookRepository implements BookRepository {
    public List<Book> findAll() {
        // 从数据库获取数据
    }
}

class BookRecommender {
    private BookRepository repository;

    BookRecommender(BookRepository repository) {
        this.repository = repository;
    }

    List<Book> recommendBooks(User user) {
        List<Book> books = repository.findAll();
        // 推荐逻辑
    }
}

👉 高层模块(BookRecommender)依赖于抽象(BookRepository),而不是具体实现。


✅ 6. 迪米特法则(LoD)

问题:对象之间耦合太紧,一个类知道太多其他类的内部细节。

解决

class Library {
    private BookCatalog catalog;

    public List<Book> search(String keyword) {
        return catalog.search(keyword); // 调用内部对象的方法,外部不知道catalog的存在
    }
}

// 客户端使用:
List<Book> results = library.search("Java");

👉 外部类不知道 BookCatalog 的存在,只与 Library 打交道,降低了耦合。


✅ 总结一句话:

这些原则的核心思想是:解耦 + 可扩展 + 易维护。它们帮助我们写出更健壮、更灵活、更容易修改的代码。