外观模式 - Flutter中的一键操作大师,复杂功能的极简入口!

痛点场景:多步骤的用户注册流程

假设你的应用需要处理以下注册步骤:

  1. 验证邮箱格式
  2. 检查密码强度
  3. 调用注册API
  4. 保存用户Token
  5. 初始化用户配置
  6. 同步基础数据
  7. 发送欢迎邮件

传统实现方式:

Future<void> registerUser(String email, String password) async {
  // 1. 验证邮箱
  if (!EmailValidator.validate(email)) {
    throw InvalidEmailException();
  }
  
  // 2. 检查密码
  if (!PasswordValidator.isStrongEnough(password)) {
    throw WeakPasswordException();
  }
  
  // 3. 调用API
  final response = await ApiClient.post('/register', {
    'email': email,
    'password': password,
  });
  
  // 4. 保存Token
  await SecureStorage.save('token', response['token']);
  
  // 5. 初始化配置
  await Preferences.initUserSettings();
  
  // 6. 同步数据
  await DataSynchronizer.syncBaseData();
  
  // 7. 发送邮件
  await EmailService.sendWelcome(email);
}

问题爆发点:

  • 调用方需要了解所有步骤
  • 修改流程需要调整多处调用
  • 难以复用注册逻辑
  • 错误处理分散在各处

外观模式解决方案

核心思想: 为子系统中的一组接口提供一个统一的更高层次的接口,使子系统更容易使用。

三个关键角色:

  1. 外观类(Facade): 提供简化的统一接口
  2. 子系统类(Subsystem): 实现具体功能
  3. 客户端(Client): 通过外观与子系统交互

Flutter用户注册外观实现

1. 创建外观类
class UserRegistrationFacade {
  final ApiClient _api;
  final SecureStorage _storage;
  final EmailService _emailService;
  
  UserRegistrationFacade({
    ApiClient? api,
    SecureStorage? storage,
    EmailService? emailService,
  }) : _api = api ?? ApiClient(),
       _storage = storage ?? SecureStorage(),
       _emailService = emailService ?? EmailService();
  
  Future<User> register(String email, String password) async {
    try {
      // 验证输入
      _validateInput(email, password);
      
      // 执行注册流程
      final user = await _registerUser(email, password);
      await _initializeUser(user);
      
      return user;
    } catch (e) {
      // 统一错误处理
      if (e is! UserRegistrationException) {
        throw UserRegistrationException('注册失败: ${e.toString()}');
      }
      rethrow;
    }
  }
  
  void _validateInput(String email, String password) {
    if (!EmailValidator.validate(email)) {
      throw InvalidEmailException();
    }
    if (!PasswordValidator.isStrongEnough(password)) {
      throw WeakPasswordException();
    }
  }
  
  Future<User> _registerUser(String email, String password) async {
    final response = await _api.post('/register', {
      'email': email,
      'password': password,
    });
    
    await _storage.save('token', response['token']);
    return User.fromJson(response['user']);
  }
  
  Future<void> _initializeUser(User user) async {
    await Future.wait([
      Preferences.initUserSettings(),
      DataSynchronizer.syncBaseData(),
      _emailService.sendWelcome(user.email),
    ]);
  }
}
2. 在Flutter中使用
class RegistrationPage extends StatefulWidget {
  
  _RegistrationPageState createState() => _RegistrationPageState();
}

class _RegistrationPageState extends State<RegistrationPage> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  final _registrationFacade = UserRegistrationFacade();
  
  Future<void> _submit() async {
    if (!_formKey.currentState!.validate()) return;
    
    try {
      setState(() => _isLoading = true);
      final user = await _registrationFacade.register(
        _emailController.text,
        _passwordController.text,
      );
      Navigator.push(context, HomePage.route(user));
    } on UserRegistrationException catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(e.message)),
      );
    } finally {
      setState(() => _isLoading = false);
    }
  }
  
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Form(
        key: _formKey,
        child: Column(
          children: [
            TextFormField(controller: _emailController),
            TextFormField(controller: _passwordController),
            ElevatedButton(
              onPressed: _isLoading ? null : _submit,
              child: _isLoading 
                  ? CircularProgressIndicator()
                  : Text('注册'),
            ),
          ],
        ),
      ),
    );
  }
}

Flutter中的实际应用场景

场景1:相机功能封装
class CameraFacade {
  final CameraController _controller;
  
  Future<void> initialize() async {
    await _controller.initialize();
    await _controller.lockCaptureOrientation();
  }
  
  Future<XFile> takePhoto() async {
    try {
      await _controller.setFlashMode(FlashMode.auto);
      return await _controller.takePicture();
    } catch (e) {
      throw CameraException('拍照失败: $e');
    }
  }
  
  Future<void> dispose() async {
    await _controller.setFlashMode(FlashMode.off);
    await _controller.dispose();
  }
}

// 使用
final camera = CameraFacade(CameraController(...));
await camera.initialize();
final photo = await camera.takePhoto();
场景2:支付流程简化
class PaymentFacade {
  Future<PaymentResult> pay(
    double amount, 
    PaymentMethod method,
  ) async {
    // 验证支付信息
    // 调用支付网关
    // 处理支付结果
    // 更新订单状态
    // 发送支付通知
    return UnifiedPaymentResult(...);
  }
}

// 使用
final result = await PaymentFacade().pay(100, PaymentMethod.alipay);
场景3:应用初始化
class AppInitializer {
  static Future<void> initialize() async {
    await Future.wait([
      Firebase.initializeApp(),
      Hive.initFlutter(),
      Preferences.initialize(),
      CrashReporting.setup(),
    ]);
    await DataPreloader.cacheEssentialData();
  }
}

// 在main中使用
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await AppInitializer.initialize();
  runApp(MyApp());
}

外观模式与状态管理结合

将复杂状态操作封装在外观中:

class ShoppingCartFacade with ChangeNotifier {
  final List<Product> _items = [];
  final InventoryService _inventory;
  final DiscountCalculator _discount;
  
  void addItem(Product product) async {
    if (!await _inventory.checkStock(product.id)) {
      throw OutOfStockException();
    }
    
    _items.add(product);
    _applyDiscounts();
    notifyListeners();
  }
  
  Future<void> checkout() async {
    await ApiClient.post('/checkout', {
      'items': _items.map((i) => i.toJson()).toList(),
    });
    _items.clear();
    notifyListeners();
  }
  
  void _applyDiscounts() {
    // 复杂的折扣计算逻辑...
  }
}

// 在Widget中使用
Consumer<ShoppingCartFacade>(
  builder: (context, cart, child) {
    return Text('总价: ${cart.totalPrice}');
  }
)

外观模式最佳实践

  1. 何时使用外观模式:

    • 需要为复杂子系统提供简单接口
    • 需要减少客户端与子系统的耦合
    • 需要分层子系统结构
    • 需要统一入口处理横切关注点(如日志、验证)
  2. Flutter特化技巧:

    // 组合多个外观
    class SuperFacade {
      final AuthFacade _auth;
      final PaymentFacade _payment;
      
      Future<void> purchasePremium() async {
        await _auth.ensureLoggedIn();
        await _payment.upgradeToPremium();
        await _auth.refreshUserStatus();
      }
    }
    
    // 提供便捷的默认实例
    class QuickActions {
      static final _instance = QuickActions._();
      factory QuickActions() => _instance;
      
      Future<void> shareApp() async {
        await Share.share('Check out this awesome app!');
      }
    }
    
  3. 性能优化:

    // 懒加载子系统
    class LazyFacade {
      HeavyService? _service;
      
      Future<void> execute() async {
        _service ??= await HeavyService.create();
        await _service!.doWork();
      }
    }
    
  4. 测试策略:

    test('注册外观应验证邮箱格式', () {
      final facade = UserRegistrationFacade();
      expect(
        () => facade.register('invalid-email', 'Password123!'),
        throwsA(isA<InvalidEmailException>()),
      );
    });
    

外观模式 vs 中介者模式

特性 外观模式 中介者模式
目的 简化子系统调用 协调对象间通信
知晓度 外观知晓所有子系统 中介者不一定知道所有对象
方向 单向(客户端→子系统) 多向(对象间相互通信)
典型应用 API封装、复杂流程简化 聊天室、表单验证

外观模式的高级变体

1. 可配置外观
class ConfigurableFacade {
  final Map<Type, dynamic> _services = {};
  
  void registerService<T>(T service) {
    _services[T] = service;
  }
  
  T getService<T>() {
    if (!_services.containsKey(T)) {
      throw ServiceNotRegisteredException();
    }
    return _services[T] as T;
  }
}
2. 分层外观
class HighLevelFacade {
  final MidLevelFacade _midLevel;
  
  void performComplexOperation() {
    _midLevel.startProcess();
    _midLevel.intermediateStep();
    _midLevel.finalize();
  }
}

class MidLevelFacade {
  final LowLevelService _service;
  
  void startProcess() {
    _service.initialize();
    _service.validate();
  }
}
3. 智能代理外观
class SmartFacade {
  Future<Result> handleRequest(Request request) async {
    if (cache.has(request.key)) {
      return cache.get(request.key);
    }
    
    final result = await _backendService.process(request);
    
    if (result.shouldCache) {
      cache.set(request.key, result);
    }
    
    return result;
  }
}

总结:外观模式是你的复杂系统"快捷键"

  • 核心价值: 隐藏复杂性,提供简洁易用的高级接口
  • Flutter优势:
    • 简化第三方库的使用
    • 统一复杂操作流程
    • 降低组件间的耦合度
    • 便于替换底层实现
  • 适用场景: API封装、插件集成、应用初始化、复杂业务流程

设计启示: 当你面对一个功能强大的"瑞士军刀"但只需要常用功能时,外观模式就是你的"快捷按钮",让你一键直达核心功能!

你可能感兴趣的:(flutter,外观模式,flutter,javascript)