跨平台开发下的策略模式

跨平台开发的核心目标是实现一套业务逻辑在多平台高效运行。

但底层 API、文件系统、权限机制等平台特性的差异,给代码维护带来了巨大挑战。

直接在业务代码中嵌入大量 if/else 进行平台判断,会导致代码耦合严重、扩展性差,最终演变为难以维护的 "面条代码"。

常见的跨平台差异点

跨平台开发中需要处理的典型差异包括:

  • 文件系统:路径分隔符(/\)、文件编码、权限管理机制。
  • 网络交互:平台 SDK 差异、请求处理方式、安全策略。
  • UI 渲染:原生控件体系、Web 视图集成、分辨率适配。
  • 系统服务:通知机制、定位服务、蓝牙等硬件交互。

使用策略模式

策略模式通过分离抽象与实现,完美解决跨平台开发中的适配问题:

  • 定义统一接口:抽象出平台无关的行为契约,使高层模块只关注 "做什么",无需关心 "怎么做"。
  • 平台特定实现:为每个平台提供独立的策略类,封装具体实现细节,新增平台时无需修改现有代码。
  • 动态策略选择:高层模块依赖抽象接口,可在运行时根据环境自动选择或动态切换策略实现。

示例:跨平台文件系统适配

1. 定义抽象接口

首先定义文件系统操作的抽象接口,屏蔽各平台差异:

ts 复制代码
export interface IFileSystem {
  writeFile(path: string, content: string): Promise<void>
  readFile(path: string): Promise<string>
  deleteFile(path: string): Promise<void>
  createFolder(path: string): Promise<void>
  deleteFolder(path: string): Promise<void>
}

2. 实现平台特定策略

为各平台实现具体策略类,封装平台特有逻辑:

ts 复制代码
// Windows平台实现
export class WindowsFileSystem implements IFileSystem {
  async writeFile(path: string, content: string): Promise<void> {
    // Windows特定文件写入逻辑
  }
  
  // 其他方法实现...
}

// Linux平台实现
export class LinuxFileSystem implements IFileSystem {
  async writeFile(path: string, content: string): Promise<void> {
    // Linux特定文件写入逻辑
  }
  
  // 其他方法实现...
}

// macOS平台实现
export class MacFileSystem implements IFileSystem {
  async writeFile(path: string, content: string): Promise<void> {
    // macOS特定文件写入逻辑
  }
  
  // 其他方法实现...
}

3. 策略工厂与访问封装

使用工厂模式管理策略实例,配合单例模式确保全局一致性:

这里使用单例模式是因为平台是固定的,不会变化,不可能说程序在 Windows 运行到一半突然切换到 Linux 去。

ts 复制代码
type PlatformType = 'win32' | 'linux' | 'darwin'

// 策略工厂:负责创建平台对应的策略实例
class FileSystemStrategyFactory {
  static createStrategy(): IFileSystem {
    const platform = process.platform as PlatformType;
  
    const strategies: Record<PlatformType, new () => IFileSystem> = {
      win32: WindowsFileSystem,
      linux: LinuxFileSystem,
      darwin: MacFileSystem
    };
  
    const StrategyClass = strategies[platform];
    if (!StrategyClass) {
      throw new Error(`Unsupported platform: ${platform}`);
    }
  
    return new StrategyClass();
  }
}

// 对外暴露的文件系统服务
export class FileSystemService {
  private static instance: FileSystemService;
  private strategy: IFileSystem;
  
  // 私有构造函数确保只能通过getInstance创建
  private constructor() {
    this.strategy = FileSystemStrategyFactory.createStrategy();
  }
  
  // 单例模式获取服务实例
  static getInstance(): FileSystemService {
    if (!FileSystemService.instance) {
      FileSystemService.instance = new FileSystemService();
    }
    return FileSystemService.instance;
  }
  
  // 代理策略方法,对外提供统一接口
  async writeFile(path: string, content: string): Promise<void> {
    return this.strategy.writeFile(path, content);
  }
  
  async readFile(path: string): Promise<string> {
    return this.strategy.readFile(path);
  }
  
  async deleteFile(path: string): Promise<void> {
    return this.strategy.deleteFile(path);
  }
  
  async createFolder(path: string): Promise<void> {
    return this.strategy.createFolder(path);
  }
  
  async deleteFolder(path: string): Promise<void> {
    return this.strategy.deleteFolder(path);
  }
}
相关推荐
geovindu16 小时前
rust:Builder Pattern
开发语言·设计模式·rust·建造者模式
小王师傅6618 小时前
【设计模式】装饰模式(三):从装饰模式看 Java 与面向对象设计(原理篇)
设计模式
流浪00119 小时前
Linux系统篇34——信号(六):信号处理期间又来了怎么办?——sigaction、sa_mask、可重入函数与 volatile
linux·运维·面试·操作系统·信号处理·信号
Zane199420 小时前
从一次支付渠道扩展需求,看懂"多用组合少用继承"到底在说什么
设计模式
布莱克60520 小时前
理解虚拟内存:概念、动机与地址映射原理
操作系统·虚拟内存
geovindu21 小时前
CSharp:Condition Variable Pattern
后端·设计模式·c#·.net·.netcore·条件变量模式·同步型模式
geovindu1 天前
sql: Data Modeling Patterns using mysql
sql·mysql·设计模式·数据库开发
sarasuki2 天前
失败重试:Agent 中指数退避的正确姿势
人工智能·设计模式·agent
Zane19942 天前
为什么你写的 Java 代码"看着面向对象、实际是面向过程"?
设计模式
geovindu2 天前
sql: Data Modeling Patterns
数据库·sql·设计模式·sqlserver