设计模式和设计原则-中高级架构思路-面向接口编程

历史文章参见

设计模式-23种设计模式的说法-掘金

每日知识-设计模式-状态机模式-掘金

每日知识-设计模式-观察者模式 - 掘金

cpp笔记第3篇-C++多线程单例模式单例模式 - 掘金


今天讲讲面向接口编程的核心思想,它可以看到各种设计模式的一种杂糅。

面向接口编程的核心思想

以实际的代码举例子,我最近在写一个安卓的笔记程序,使用到了面向接口的编程方法,下面我以具体的类举例来说明面向接口编程的思想,以及后文解释,面向接口编程可以体现哪些设计模式。

一、依赖接口,而不是具体实现

java 复制代码
// ❌ 面向具体类(耦合)
public class NoteListManager {
    private MainActivity activity; // 直接依赖 MainActivity
}

// ✅ 面向接口(解耦)
public class NoteListManager {
    private INoteListCallback callback; // 依赖接口
    // 优势:只要接口不变,实现类怎么变都行
}

二、在这个场景中的体现

1. 定义接口(契约)
java 复制代码
// INoteListCallback.java - 定义"契约"
public interface INoteListCallback {
    // 定义需要什么方法,不关心怎么实现
    String formatTimestamp(long timestamp);
    int dpToPx(int dp);
    NoteDbHelper getDbHelper();
}
2. 实现接口(具体实现)
java 复制代码
// MainActivity.java - 实现接口
public class MainActivity implements INoteListCallback {
    // 提供具体实现
    @Override
    public String formatTimestamp(long timestamp) {
        // 具体怎么格式化,MainActivity 自己决定
    }
}
3. 使用接口(依赖抽象)
java 复制代码
// NoteListManager.java - 只依赖接口
public class NoteListManager {
    private INoteListCallback callback; // 只依赖接口,不依赖具体类
    
    public void displayNote(Note note) {
        // 通过接口调用,不知道具体是哪个类实现的
        String time = callback.formatTimestamp(note.getTimestamp());
    }
}

三、面向接口编程的优势

1. 解耦
java 复制代码
// NoteListManager 不知道 MainActivity 的存在
// 它只知道有一个对象实现了 INoteListCallback 接口
// 可以是 MainActivity,也可以是 TestActivity,也可以是 MockActivity
2. 可测试性
java 复制代码
// 测试时,可以用 Mock 实现
class MockCallback implements INoteListCallback {
    @Override
    public String formatTimestamp(long timestamp) {
        return "Mock时间"; // 测试用的简单实现
    }
}

// 测试 NoteListManager
NoteListManager manager = new NoteListManager();
manager.initialize(listView, new MockCallback()); // 用 Mock 测试
3. 可扩展性
java 复制代码
// 以后可以有不同的实现
class AnotherActivity implements INoteListCallback {
    @Override
    public String formatTimestamp(long timestamp) {
        return "另一种格式"; // 不同的实现方式
    }
}

// NoteListManager 不需要改,只需要传入不同的实现
manager.initialize(listView, new AnotherActivity());

四、设计原则体现

1. 依赖倒置原则(DIP)
复制代码
高层模块(NoteListManager)不应该依赖低层模块(MainActivity)
两者都应该依赖抽象(INoteListCallback)
2. 开闭原则(OCP)
复制代码
对扩展开放:可以添加新的实现类
对修改关闭:NoteListManager 不需要修改

五、优点总结

markdown 复制代码
面向接口编程 = 定义接口(契约)
            = 实现接口(具体实现)
            = 使用接口(依赖抽象)
            = 解耦、可测试、可扩展

Callback 就是面向接口编程思想的实际体现。下面我们看看哪些具体的设计模式都跟面向接口编程有关。

与面向接口编程有关的设计模式

常见的一种是策略模式。当然,面向接口编程不仅体现在策略模式 中,还贯穿于多种行为型和结构型模式

一、在行为型模式中的体现

1. 观察者模式(Observer) ⭐️ 高度体现

java 复制代码
// 定义接口
interface Observer {
    void update(String message);
}

interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

// 实现接口
class User implements Observer {
    @Override
    public void update(String message) {
        System.out.println("收到消息: " + message);
    }
}

// 使用接口
NewsPublisher publisher = new NewsPublisher();
publisher.registerObserver(new User());  // 依赖接口,不依赖具体类

接口思维:Observer是观察者的抽象,Subject是主题的抽象。双方通过接口通信。

2. 命令模式(Command) ⭐️ 核心就是接口

java 复制代码
// 定义命令接口
interface Command {
    void execute();
    void undo();
}

// 不同实现
class SaveCommand implements Command {
    @Override
    public void execute() {
        // 保存逻辑
    }
}

class DeleteCommand implements Command {
    @Override
    public void execute() {
        // 删除逻辑
    }
}

// 使用命令
Button saveBtn = new Button(new SaveCommand());  // 传入接口

接口思维:将请求封装为对象,所有命令都实现Command接口,调用者只依赖接口。

3. 状态模式(State)

每日知识-设计模式-状态模式- 掘金

java 复制代码
interface State {
    void handle(Context context);
}

class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        context.setState(new ConcreteStateB());  // 切换到另一个状态
    }
}

接口思维:状态抽象为接口,上下文对象依赖State接口而不是具体状态。

4. 模板方法模式(Template Method)

java 复制代码
abstract class DataProcessor {
    // 模板方法 - 定义算法骨架
    public final void process() {
        readData();      // 固定步骤
        transformData(); // 抽象方法,子类实现
        saveData();      // 固定步骤
    }
    
    // 抽象方法 - 通过实现来变化
    protected abstract void transformData();
}

接口思维:虽然用抽象类,但思想一致 - 定义算法框架,具体步骤由子类实现。

二、在结构型模式中的体现

1. 适配器模式(Adapter) - 核心是统一接口

java 复制代码
// 目标接口(期望的接口)
interface MediaPlayer {
    void play(String audioType, String fileName);
}

// 已有的类,接口不兼容
class Mp4Player {
    public void playMp4(String fileName) { /*...*/ }
}

// 适配器 - 实现目标接口,包装已有类
class Mp4Adapter implements MediaPlayer {
    private Mp4Player mp4Player;
    
    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equals("mp4")) {
            mp4Player.playMp4(fileName);  // 适配
        }
    }
}

接口思维:通过适配器统一不同系统的接口,客户端只依赖MediaPlayer接口。

2. 桥接模式(Bridge) - 抽象与实现分离

java 复制代码
// 抽象部分
abstract class Shape {
    protected Color color;  // 桥接 - 组合Color接口
    
    public Shape(Color color) {
        this.color = color;
    }
    
    abstract void draw();
}

// 实现部分接口
interface Color {
    String fill();
}

// 具体实现
class Red implements Color {
    @Override
    public String fill() {
        return "红色";
    }
}

// 使用
Shape circle = new Circle(new Red());  // 通过接口组合

接口思维:将抽象(Shape)与实现(Color)解耦,通过接口组合。

3. 代理模式(Proxy)

java 复制代码
interface Image {
    void display();
}

class RealImage implements Image {
    @Override
    public void display() {
        // 实际加载图片
    }
}

class ProxyImage implements Image {  // 代理类也实现相同接口
    private RealImage realImage;
    
    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage();  // 延迟加载
        }
        realImage.display();
    }
}

接口思维:代理类和真实类实现相同的接口,客户端无感知。

三、在创建型模式中的体现

1. 工厂方法模式(Factory Method)

java 复制代码
interface Product {
    void use();
}

interface Creator {
    Product createProduct();  // 工厂方法 - 返回接口
}

class ConcreteCreator implements Creator {
    @Override
    public Product createProduct() {
        return new ConcreteProduct();  // 返回具体产品,但声明为Product接口
    }
}

接口思维:工厂返回接口类型,客户端不依赖具体产品类。

2. 抽象工厂模式(Abstract Factory)

java 复制代码
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

interface Button {
    void paint();
}

// 客户端代码
class Application {
    private Button button;
    
    public Application(GUIFactory factory) {  // 依赖工厂接口
        button = factory.createButton();
    }
}

接口思维:整套产品族通过接口定义,具体工厂实现接口。

四、面向接口编程的层次

第一层:技术实现

java 复制代码
// 简单的接口定义与实现
interface A { void doSomething(); }
class B implements A { ... }

第二层:设计模式

java 复制代码
// 模式级别的接口应用
// 1. 策略模式:定义算法族,使其可以互换
// 2. 观察者模式:定义发布-订阅的通信机制
// 3. 命令模式:将请求封装为对象
// 4. 状态模式:将状态抽象为接口

第三层:架构思想

java 复制代码
// 系统架构层面的接口
// - 依赖倒置:高层模块不依赖低层模块,都依赖抽象
// - 接口隔离:多个专用接口优于一个通用接口
// - 六边形架构:通过端口(接口)与外部世界通信

五、实际项目中的应用启示

何时选择哪种模式?

场景 适合的模式 接口的作用
算法可互换 策略模式 定义算法接口
对象状态变化 状态模式 定义状态接口
请求需要封装 命令模式 定义命令接口
解耦通知机制 观察者模式 定义观察者接口
统一不同接口 适配器模式 定义目标接口
延迟/控制访问 代理模式 定义主体接口

一个综合示例:电商订单系统

java 复制代码
// 策略模式:不同的折扣策略
interface DiscountStrategy {
    double calculateDiscount(Order order);
}

// 状态模式:订单状态
interface OrderState {
    void next(Order order);
    void previous(Order order);
    void process(Order order);
}

// 观察者模式:订单状态通知
interface OrderObserver {
    void update(Order order);
}

// 命令模式:订单操作
interface OrderCommand {
    void execute();
    void undo();
}

总结

面向接口编程是贯穿所有设计模式的灵魂思想

  1. 策略模式:最直接的体现,但远不止于此
  2. 行为型模式 中大部分都基于接口:
    • 观察者、命令、状态、策略等核心都是接口抽象
  3. 结构型模式 通过接口实现结构解耦:
    • 适配器统一接口,桥接分离抽象与实现
  4. 创建型模式通过接口隐藏创建细节

核心思想 :面向接口编程不仅仅是写一个interface,而是:

  • 依赖抽象,而不是具体
  • 定义契约,而不是实现
  • 关注能做什么,而不是怎么做

这在GoF的23种设计模式中都有深刻体现,是面向对象设计的精髓所在。

相关推荐
大厂技术总监下海16 小时前
为何顶尖科技公司都依赖它?解码 Protocol Buffers 背后的高性能、可演进设计模式
分布式·设计模式
EnzoRay17 小时前
代理模式
设计模式
weixin_4784333217 小时前
iluwatar 设计模式
java·开发语言·设计模式
郝学胜-神的一滴19 小时前
Python面向对象编程:解耦、多态与魔法艺术
java·开发语言·c++·python·设计模式·软件工程
__万波__19 小时前
二十三种设计模式(十六)--迭代器模式
java·设计模式·迭代器模式
范纹杉想快点毕业1 天前
返璞归真还是拥抱现代?——嵌入式研发中的“裸机开发”与RTOS全景解析
c语言·数据库·mongodb·设计模式·nosql
代码笔耕2 天前
面向对象开发实践之消息中心设计(四)--- 面向变化的定力
java·设计模式·架构
程序员泠零澪回家种桔子2 天前
ReAct Agent 后端架构解析
后端·spring·设计模式·架构
阿闽ooo2 天前
深入浅出享元模式:从图形编辑器看对象复用的艺术
c++·设计模式·编辑器·享元模式