策略模式 - Flutter中的算法超市,运行时自由切换“计算法则“!

痛点场景:支付流程的if-else地狱

假设你正在开发一个电商App,需要支持多种支付方式:

void processPayment(String method, double amount) {
  if (method == 'alipay') {
    print('调用支付宝SDK,支付¥$amount');
    // 支付宝特定逻辑...
  } else if (method == 'wechat') {
    print('调用微信支付SDK,支付¥$amount');
    // 微信特定逻辑...
  } else if (method == 'creditCard') {
    print('调用银联接口,支付¥$amount');
    // 信用卡验证逻辑...
  } else if (method == 'applePay') {
    print('调用Apple Pay API,支付¥$amount');
    // Apple Pay特定配置...
  }
  // 未来新增支付方式还要修改这里...
}

问题爆发点:

  • 每新增一种支付方式就要修改核心类
  • 所有支付逻辑耦合在一起
  • 难以单独测试某种支付方式
  • 违反开闭原则(对扩展开放,对修改关闭)

策略模式解决方案

核心思想: 定义一系列算法,将每个算法封装起来,并使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。

三个关键角色:

  1. 上下文(Context): 持有策略引用,用策略接口与具体策略交互
  2. 策略接口(Strategy): 声明所有支持的算法接口
  3. 具体策略(ConcreteStrategy): 实现策略接口的具体算法类

Flutter支付策略实现

1. 定义策略接口
abstract class PaymentStrategy {
  Future<bool> pay(double amount);
  String get name;
  Widget get icon;
}
2. 实现具体策略
// 支付宝策略
class AlipayStrategy implements PaymentStrategy {
  
  String get name => '支付宝';
  
  
  Widget get icon => Icon(Icons.payment, color: Colors.blue);
  
  
  Future<bool> pay(double amount) async {
    print('调用支付宝SDK,支付¥$amount');
    // 实际调用支付宝插件...
    await Future.delayed(Duration(seconds: 1));
    return true; // 模拟支付成功
  }
}

// 微信支付策略
class WechatPayStrategy implements PaymentStrategy {
  
  String get name => '微信支付';
  
  
  Widget get icon => Icon(Icons.wechat, color: Colors.green);
  
  
  Future<bool> pay(double amount) async {
    print('调用微信支付SDK,支付¥$amount');
    // 实际调用微信插件...
    await Future.delayed(Duration(seconds: 1));
    return true;
  }
}

// 信用卡策略
class CreditCardStrategy implements PaymentStrategy {
  final String cardNumber;
  final String cvv;
  
  CreditCardStrategy(this.cardNumber, this.cvv);
  
  
  String get name => '信用卡';
  
  
  Widget get icon => Icon(Icons.credit_card, color: Colors.indigo);
  
  
  Future<bool> pay(double amount) async {
    print('验证信用卡$cardNumber,支付¥$amount');
    // 验证逻辑...
    if (cardNumber.isEmpty || cvv.isEmpty) return false;
    await Future.delayed(Duration(seconds: 2));
    return true;
  }
}
3. 创建支付上下文
class PaymentContext {
  PaymentStrategy? _strategy;
  
  void setStrategy(PaymentStrategy strategy) {
    _strategy = strategy;
  }
  
  Future<bool> executePayment(double amount) async {
    if (_strategy == null) throw Exception('请先设置支付策略');
    return await _strategy!.pay(amount);
  }
  
  Widget? get strategyIcon => _strategy?.icon;
  String? get strategyName => _strategy?.name;
}
4. 在Flutter中使用
class PaymentPage extends StatefulWidget {
  
  _PaymentPageState createState() => _PaymentPageState();
}

class _PaymentPageState extends State<PaymentPage> {
  final PaymentContext _paymentContext = PaymentContext();
  double _amount = 99.99;
  PaymentStrategy? _selectedStrategy;

  final List<PaymentStrategy> _strategies = [
    AlipayStrategy(),
    WechatPayStrategy(),
    CreditCardStrategy('4111111111111111', '123'),
  ];

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('选择支付方式')),
      body: Column(
        children: [
          // 金额显示
          Text('¥$_amount', style: TextStyle(fontSize: 24)),
          
          // 策略选择列表
          ..._strategies.map((strategy) => RadioListTile<PaymentStrategy>(
            title: Row(children: [
              strategy.icon,
              SizedBox(width: 10),
              Text(strategy.name),
            ]),
            value: strategy,
            groupValue: _selectedStrategy,
            onChanged: (value) => setState(() {
              _selectedStrategy = value;
              _paymentContext.setStrategy(value!);
            }),
          )),
          
          // 支付按钮
          ElevatedButton(
            onPressed: _selectedStrategy == null ? null : _handlePayment,
            child: Text('立即支付'),
          ),
        ],
      ),
    );
  }

  Future<void> _handlePayment() async {
    final success = await _paymentContext.executePayment(_amount);
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text(success ? '支付成功' : '支付失败'),
        content: Text('${_paymentContext.strategyName} ¥$_amount'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx),
            child: Text('确定'),
          ),
        ],
      ),
    );
  }
}

Flutter中的实际应用场景

场景1:动态排序策略
// 排序策略接口
abstract class SortStrategy {
  List<Product> sort(List<Product> items);
}

// 价格升序策略
class PriceAscSort implements SortStrategy {
  
  List<Product> sort(List<Product> items) {
    return List.from(items)..sort((a, b) => a.price.compareTo(b.price));
  }
}

// 销量降序策略
class SalesDescSort implements SortStrategy {
  
  List<Product> sort(List<Product> items) {
    return List.from(items)..sort((a, b) => b.sales.compareTo(a.sales));
  }
}

// 在商品列表中使用
class ProductList extends StatelessWidget {
  final SortStrategy sortStrategy;
  final List<Product> products;
  
  ProductList({required this.sortStrategy, required this.products});
  
  
  Widget build(BuildContext context) {
    final sortedProducts = sortStrategy.sort(products);
    return ListView.builder(
      itemCount: sortedProducts.length,
      itemBuilder: (ctx, i) => ProductItem(sortedProducts[i]),
    );
  }
}

// 切换排序方式
ProductList(
  sortStrategy: _isPriceSort ? PriceAscSort() : SalesDescSort(),
  products: _products,
)
场景2:地图导航策略
// 导航策略接口
abstract class NavigationStrategy {
  Route planRoute(Location start, Location end);
}

// 驾车策略
class DrivingStrategy implements NavigationStrategy {
  
  Route planRoute(Location start, Location end) {
    print('计算驾车路线:$start -> $end');
    // 调用驾车路线API...
    return Route(/*...*/);
  }
}

// 步行策略
class WalkingStrategy implements NavigationStrategy {
  
  Route planRoute(Location start, Location end) {
    print('计算步行路线:$start -> $end');
    // 调用步行路线API...
    return Route(/*...*/);
  }
}

// 导航上下文
class NavigatorContext {
  NavigationStrategy _strategy = DrivingStrategy(); // 默认驾车
  
  void setStrategy(NavigationStrategy strategy) {
    _strategy = strategy;
  }
  
  void navigate(Location start, Location end) {
    final route = _strategy.planRoute(start, end);
    _displayRoute(route);
  }
}
场景3:数据缓存策略
// 缓存策略接口
abstract class CacheStrategy {
  Future<String?> get(String key);
  Future<void> set(String key, String value);
}

// 内存缓存
class MemoryCache implements CacheStrategy {
  final Map<String, String> _cache = {};
  
  
  Future<String?> get(String key) async => _cache[key];
  
  
  Future<void> set(String key, String value) async {
    _cache[key] = value;
  }
}

// 本地存储缓存
class LocalStorageCache implements CacheStrategy {
  
  Future<String?> get(String key) async {
    return await SharedPreferences.getInstance()
      .then((prefs) => prefs.getString(key));
  }
  
  
  Future<void> set(String key, String value) async {
    await SharedPreferences.getInstance()
      .then((prefs) => prefs.setString(key, value));
  }
}

// 在数据仓库中使用
class UserRepository {
  final CacheStrategy _cacheStrategy;
  
  UserRepository({CacheStrategy? cache}) 
    : _cacheStrategy = cache ?? MemoryCache();
  
  Future<User> fetchUser(String id) async {
    final cached = await _cacheStrategy.get('user_$id');
    if (cached != null) return User.fromJson(cached);
    
    // 从网络获取...
    final user = await api.getUser(id);
    await _cacheStrategy.set('user_$id', user.toJson());
    return user;
  }
}

策略模式与Flutter状态管理的结合

将策略模式与Provider结合实现动态主题切换:

// 主题策略接口
abstract class ThemeStrategy {
  ThemeData get themeData;
  Color get primaryColor;
}

// 明亮主题策略
class LightThemeStrategy implements ThemeStrategy {
  
  ThemeData get themeData => ThemeData.light();
  
  
  Color get primaryColor => Colors.blue;
}

// 暗黑主题策略
class DarkThemeStrategy implements ThemeStrategy {
  
  ThemeData get themeData => ThemeData.dark();
  
  
  Color get primaryColor => Colors.blueGrey;
}

// 主题策略提供者
class ThemeProvider extends ChangeNotifier {
  ThemeStrategy _currentStrategy = LightThemeStrategy();
  
  ThemeStrategy get currentStrategy => _currentStrategy;
  
  void toggleTheme() {
    _currentStrategy = _currentStrategy is LightThemeStrategy
      ? DarkThemeStrategy()
      : LightThemeStrategy();
    notifyListeners();
  }
}

// 在MaterialApp中使用
MaterialApp(
  theme: context.watch<ThemeProvider>().currentStrategy.themeData,
  // ...
)

// 切换主题
context.read<ThemeProvider>().toggleTheme();

策略模式最佳实践

  1. 何时使用策略模式:

    • 一个系统需要动态地在几种算法中选择一种
    • 有多个条件语句的相同行为
    • 需要隔离算法细节与使用场景
    • 算法可能在未来扩展或变化
  2. Flutter特化技巧:

    // 使用策略工厂简化创建
    class StrategyFactory {
      static PaymentStrategy create(String type) {
        switch(type) {
          case 'alipay': return AlipayStrategy();
          case 'wechat': return WechatPayStrategy();
          default: throw Exception('未知策略类型');
        }
      }
    }
    
    // 策略组合
    class CompositeStrategy implements PaymentStrategy {
      final List<PaymentStrategy> _strategies;
      
      CompositeStrategy(this._strategies);
      
      
      Future<bool> pay(double amount) async {
        for (final strategy in _strategies) {
          final success = await strategy.pay(amount);
          if (!success) return false;
        }
        return true;
      }
    }
    
  3. 性能优化:

    // 缓存策略实例
    class StrategyCache {
      static final Map<Type, PaymentStrategy> _cache = {};
      
      static T getStrategy<T extends PaymentStrategy>(T Function() create) {
        if (!_cache.containsKey(T)) {
          _cache[T] = create();
        }
        return _cache[T] as T;
      }
    }
    
    // 使用缓存策略
    final strategy = StrategyCache.getStrategy(() => AlipayStrategy());
    
  4. 测试策略:

    void main() {
      test('Alipay策略测试', () async {
        final strategy = AlipayStrategy();
        final result = await strategy.pay(100);
        expect(result, isTrue);
      });
      
      test('信用卡策略验证失败测试', () async {
        final strategy = CreditCardStrategy('', ''); // 无效卡号
        final result = await strategy.pay(100);
        expect(result, isFalse);
      });
    }
    

策略模式 vs 状态模式

特性 策略模式 状态模式
目的 封装可互换的算法 管理状态相关行为
知晓性 策略相互独立 状态知道其他状态
变化触发 客户端主动设置策略 状态自动转换
典型应用 支付方式、排序算法 订单状态、播放器控制

策略模式的强大变体

1. 策略+工厂方法
abstract class Strategy {
  Widget buildButton(VoidCallback onPressed);
}

class PrimaryStrategy implements Strategy {
  
  Widget buildButton(VoidCallback onPressed) {
    return ElevatedButton(onPressed: onPressed, child: Text('Primary'));
  }
}

class StrategyFactory {
  static Strategy create(String type) {
    switch(type) {
      case 'primary': return PrimaryStrategy();
      case 'outlined': return OutlinedStrategy();
      default: throw Exception('未知策略');
    }
  }
}

// 使用
StrategyFactory.create('primary').buildButton(() {});
2. 策略+装饰器
abstract class TextDecoratorStrategy {
  String decorate(String text);
}

class BoldDecorator implements TextDecoratorStrategy {
  
  String decorate(String text) => '**$text**';
}

class ItalicDecorator implements TextDecoratorStrategy {
  
  String decorate(String text) => '*$text*';
}

class TextEditor {
  final List<TextDecoratorStrategy> _strategies = [];
  
  void addStrategy(TextDecoratorStrategy strategy) {
    _strategies.add(strategy);
  }
  
  String process(String text) {
    return _strategies.fold(text, (result, strategy) => strategy.decorate(result));
  }
}

// 使用
final editor = TextEditor()
  ..addStrategy(BoldDecorator())
  ..addStrategy(ItalicDecorator());
print(editor.process('Hello')); // 输出:**_*Hello*_**

总结:策略模式是你的算法工具箱

  • 核心价值: 定义算法家族,实现运行时灵活切换
  • Flutter优势:
    • 消除条件分支语句
    • 提高代码扩展性
    • 便于单元测试
    • 符合开闭原则
  • 适用场景: 支付方式、排序算法、导航策略、缓存机制、主题切换

�‍ 设计启示: 当你在Flutter中发现需要根据不同条件执行相似但不同的操作时,策略模式能让你的代码更优雅!

你可能感兴趣的:(flutter,策略模式,flutter,算法)