Flutter开发实战:抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式(Abstract Factory Pattern)是一种软件设计模式,它是工厂方法模式的拓展。该模式提供了一种方式来封装一组相关或依赖的工厂,这些工厂负责创建一系列对象,而不需要指定它们的具体类。它可以被视为一种工厂的工厂,用于创建其他工厂,这些工厂再负责创建不同类型的对象。

主要目的:

  • 提供一个接口来创建一组相关或依赖的对象,而不是单个对象。
  • 将具体类的创建细节与客户端代码分离,使得客户端代码与具体类的耦合度降低,更易于扩展和维护。

结构:

  1. 抽象工厂(Abstract Factory):声明一组创建对象的抽象方法,每个方法对应一类产品。
  2. 具体工厂(Concrete Factory):实现抽象工厂接口,负责创建具体的产品对象。
  3. 抽象产品(Abstract Product):声明一组产品接口,每个方法对应产品的一种功能。
  4. 具体产品(Concrete Product):实现抽象产品接口,是具体工厂创建的对象。

抽象工厂模式是一种创建型设计模式,它提供一个接口用于创建一系列相关或互相依赖的对象,而无需指定它们具体的类。

下面让我们通过两个在现实开发中经常遇到的场景,来看一下如何在Flutter中使用抽象工厂模式(Abstract Factory Pattern)

场景一:切换主题

当你需要在 UI 中使用不同的主题或样式时。可以使用抽象工厂模式来创建一个亮色主题工厂和一个暗黑主题工厂。每个工厂可以生成一套具有不同颜色和样式的组件(例如按钮、滑块和切换开关)。

dart 复制代码
// 抽象产品 (Abstract Product):定义一组产品的抽象接口,每个方法对应产品的一种功能。
abstract class AbstractAppBar {
  AppBar createAppBar(String title);
}

abstract class AbstractFloatingActionButton {
  FloatingActionButton createFloatingActionButton(IconData icon);
}

// 具体产品 (Concrete Product):实现抽象产品接口,是具体工厂创建的对象。
class LightAppBar implements AbstractAppBar {
  @override
  AppBar createAppBar(String title) {
    // 返回一个带有标题的亮色主题 AppBar
    return AppBar(
      title: Text(title),
      backgroundColor: Colors.white,
      toolbarTextStyle: const TextStyle(color: Colors.black),
      iconTheme: const IconThemeData(color: Colors.black),
    );
  }
}

class LightFloatingActionButton implements AbstractFloatingActionButton {
  @override
  FloatingActionButton createFloatingActionButton(IconData icon) {
    // 返回一个带有图标的亮色主题 FloatingActionButton
    return FloatingActionButton(
      onPressed: () {},
      child: Icon(icon),
      backgroundColor: Colors.white,
      foregroundColor: Colors.black,
    );
  }
}

class DarkAppBar implements AbstractAppBar {
  @override
  AppBar createAppBar(String title) {
    // 返回一个带有标题的暗色主题 AppBar
    return AppBar(
      title: Text(title),
      backgroundColor: Colors.black,
      toolbarTextStyle: const TextStyle(color: Colors.white),
      iconTheme: const IconThemeData(color: Colors.white),
    );
  }
}

class DarkFloatingActionButton implements AbstractFloatingActionButton {
  @override
  FloatingActionButton createFloatingActionButton(IconData icon) {
    // 返回一个带有图标的暗色主题 FloatingActionButton
    return FloatingActionButton(
      onPressed: () {},
      child: Icon(icon),
      backgroundColor: Colors.black,
      foregroundColor: Colors.white,
    );
  }
}

// 抽象工厂(Abstract Factory):定义一个创建一组产品对象的抽象接口,它包含一系列的创建方法,每个方法对应一类产品。
abstract class ThemeFactory {
  AbstractAppBar createAppBar();
  AbstractFloatingActionButton createFloatingActionButton();
}

// 具体工厂(Concrete Factory):实现抽象工厂接口,负责创建具体的产品对象。
class LightThemeFactory implements ThemeFactory {
  @override
  AbstractAppBar createAppBar() {
    return LightAppBar();
  }

  @override
  AbstractFloatingActionButton createFloatingActionButton() {
    return LightFloatingActionButton();
  }
}

class DarkThemeFactory implements ThemeFactory {
  @override
  AbstractAppBar createAppBar() {
    return DarkAppBar();
  }

  @override
  AbstractFloatingActionButton createFloatingActionButton() {
    return DarkFloatingActionButton();
  }
}

// 在应用程序中,可以如下使用这些工厂:
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // final ThemeFactory themeFactory = LightThemeFactory(); // 你可以在这里切换主题
  final ThemeFactory themeFactory = DarkThemeFactory(); // 你可以在这里切换主题

  @override
  Widget build(BuildContext context) {
    final appBar = themeFactory.createAppBar();
    final floatingActionButton = themeFactory.createFloatingActionButton();

    return MaterialApp(
      home: Scaffold(
        appBar: appBar.createAppBar('My App'),
        floatingActionButton:
            floatingActionButton.createFloatingActionButton(Icons.add),
      ),
    );
  }
}

AbstractAppBarAbstractFloatingActionButton 是抽象产品,它们定义了创建 AppBar 和 FloatingActionButton 的接口。LightAppBarLightFloatingActionButtonDarkAppBarDarkFloatingActionButton 是具体产品,它们实现了抽象产品的接口,用于创建具体的 AppBar 和 FloatingActionButton。

ThemeFactory 是抽象工厂,它定义了创建抽象产品的接口。LightThemeFactoryDarkThemeFactory 是具体工厂,它们实现了抽象工厂的接口,用于创建具体的产品。

场景二:平台差异化

在日常开发中,需要显示一些动画,这些动画在 Android 和 iOS 上有不同的行为。可能希望在 Android 上使用线性动画,而在 iOS 上使用弹性动画。

为了实现这一点,我们可以创建一个 Animation 抽象类和两个具体的类:LinearAnimationElasticAnimation

代码实现:

dart 复制代码
// 抽象类
abstract class AnimationBehavior {
  Animation<double> getAnimation(AnimationController controller);
}

// 具体实现
class LinearAnimation implements AnimationBehavior {
  @override
  Animation<double> getAnimation(AnimationController controller) {
    return Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(
        parent: controller,
        curve: Curves.linear,
      ),
    );
  }
}

class ElasticAnimation implements AnimationBehavior {
  @override
  Animation<double> getAnimation(AnimationController controller) {
    return Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(
        parent: controller,
        curve: Curves.elasticOut,
      ),
    );
  }
}

// 抽象工厂
abstract class AnimationFactory {
  AnimationBehavior getAnimationBehavior();
}

// 具体工厂
class AndroidAnimationFactory implements AnimationFactory {
  @override
  AnimationBehavior getAnimationBehavior() {
    return LinearAnimation();
  }
}

class IOSAnimationFactory implements AnimationFactory {
  @override
  AnimationBehavior getAnimationBehavior() {
    return ElasticAnimation();
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  Animation<double>? _animation;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

    AnimationFactory? animationFactory;
    if (Platform.isAndroid) {
      animationFactory = AndroidAnimationFactory();
    } else {
      animationFactory = IOSAnimationFactory();
    }

    _animation =
        animationFactory.getAnimationBehavior().getAnimation(_controller);
    _animation?.addListener(() {
      setState(() {});
    });
    _controller.repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Container(
            width: 100 * _animation!.value,
            height: 100 * _animation!.value,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }
}

创建了一个 AnimationBehavior 抽象类和两个实现该类的具体类:LinearAnimationElasticAnimation。然后,创建了一个 AnimationFactory 抽象类和两个实现该类的具体类:AndroidAnimationFactoryIOSAnimationFactory。在应用程序中,使用抽象工厂来创建一个具有适当行为的动画。这使得我们能够在不改变应用程序其余部分的情况下轻松切换动画行为。

总结

抽象工厂模式是一种设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。这是一种非常有用的模式,特别是在设计需要处理多个系列或主题的系统时。然而,就像所有设计模式一样,它有其优点和缺点。

优点

  1. 一致性:抽象工厂模式可以确保客户端代码与产品对象一起工作,而不考虑如何创建、组合和排列这些对象。当一个工厂负责创建一整个产品族的产品,我们可以保证这些产品之间的兼容性和一致性。
  2. 代码隔离:抽象工厂模式可以隔离客户端代码和具体类之间的依赖关系,使得客户端代码仅依赖于抽象接口。这使得代码更加模块化,更易于理解和维护。
  3. 替换产品系列很容易:由于抽象工厂模式在一个地方集中处理所有产品创建,因此替换整个产品系列变得非常容易。只需更换具体工厂,就可以更改应用程序中使用的产品类型。
  4. 增加新产品相对容易:通过扩展现有的工厂类,我们可以将新的产品添加到应用程序中,而无需修改已存在的客户端代码。

缺点

  1. 难以支持新种类的产品:如果需要添加一个新的产品种类,我们需要更改所有的工厂和每个工厂中的方法,这会是一个很大的改动。这违反了开闭原则,即软件实体(类、模块、函数等)应该可以扩展,但是不可修改。
  2. 可能导致过度抽象:如果只有一种类型的产品或者产品族非常简单,那么使用抽象工厂模式可能会导致不必要的复杂性和过度抽象。
  3. 增加了系统的抽象性和理解难度:抽象工厂模式中的所有产品都需要定义一个接口,这将导致系统有更多的类和对象,增加了系统的抽象性和理解难度。

在使用抽象工厂模式时,需要权衡其带来的便利性和引入的复杂性。这并不是一种适用于所有情况的解决方案,而是应该根据具体的应用场景和需求来考虑是否使用。

希望对您有所帮助谢谢!!!

相关推荐
Cerrda7 小时前
开发体验升级:UnoCSS 自定义 SVG 图标热更新方案
架构·前端框架
Kstheme11 小时前
把任何 GitHub 仓库变成系统设计课:这个开源项目做到了
架构
槑有老呆11 小时前
别再手搓 Prompt 了,那个叫"手动挡循环"
设计模式
禅思院11 小时前
路由性能高可用架构实战方案
前端·架构·前端框架
恋猫de小郭1 天前
Android 限制侧载新进展,谷歌联合国内厂商推验证计划
android·前端·flutter
恋猫de小郭1 天前
解读 Android 17 全新内存限制,有没有“豁免”后门?
android·前端·flutter
用户6919026813391 天前
Vibe Coding 开发项目的基本范式
人工智能·设计模式·代码规范
贵慜_Derek1 天前
《从零实现 Agent 系统》连载 32|闭集 IE 与小模型:分类、意图与字段抽取
人工智能·架构·agent
江米小枣tonylua2 天前
译:设计生产级 RAG 架构
架构
怕浪猫2 天前
领域特定语言(Domain-Specific Language, DSL)
设计模式·程序员·架构