<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Flutter 設計模式|工廠模式家族

      文/ 楊加康,CFUG 社區成員,《Flutter 開發之旅從南到北》作者,小米工程師

      在圍繞設計模式的話題中,工廠這個詞頻繁出現,從 簡單工廠 模式到 工廠方法 模式,再到 抽象工廠 模式。工廠名稱含義是制造產品的工業場所,應用在面向對象中,順理成章的成為了比較典型的創建型模式。

      圖源:https://media2.giphy.com/media/3ohjUKYWSqORcgIIsE/giphy.gif

      從形式上講,工廠可以是一個返回我們想要對象的一個方法/函數,即可以作為構造函數的一種抽象。

      本文,就帶大家使用 Dart 理解它們的各自的實現,以及它們之間的關系。

      簡單工廠 & factory 關鍵字

      簡單工廠模式 不在 23 種 GoF 設計模式中,卻是我們最常使用的一種編程方式。
      其中主要涉及到一個特殊的方法,專門用來提供我們想要的實例對象(對象工廠),
      我們可以將這個方法放到一個單獨的類 SimpleFactory 中,如下:

      class SimpleFactory {
      
        /// 工廠方法
        static Product createProduct(int type) {
          if (type == 1) {
            return ConcreteProduct1();
          }
          if (type == 2) {
            return ConcreteProduct2();
          }
          return ConcreteProduct();
        }
      }
      

      我們認為該方法要創建的對象同屬一個 Product 類(抽象類),并通過參數 type 指定要創建具體的對象類型。
      Dart 不支持 interface 關鍵詞,但我們可以使用 abstract 以抽象類的方式定義接口,
      然后各個具體的類型繼承實現它即可:

      /// 抽象類
      abstract class Product {
        String? name;
      }
      
      /// 實現類
      class ConcreteProduct implements Product {
        @override
        String? name = 'ConcreteProduct';
      }
      
      /// 實現類1
      class ConcreteProduct1 implements Product {
        @override
        String? name = 'ConcreteProduct1';
      }
      
      /// 實現類2
      class ConcreteProduct2 implements Product {
        @override
        String? name = 'ConcreteProduct2';
      }
      

      當我們想要在代碼中獲取對應的類型對象時,只需要通過這個方法傳入想要的類型值即可,
      我們不必關心生產如何被生產以及哪個對象被選擇的具體邏輯:

      void main() {
        final Product product = SimpleFactory.createProduct(1);
        print(product.name); // ConcreteProduct1
      }
      

      這就是 簡單工廠模式
      說到這里,就不得不提到 Dart 中特有的 factory 關鍵詞了。

      factory 關鍵詞 可以用來修飾 Dart 類的構造函數,意為 工廠構造函數,它能夠讓 的構造函數天然具有工廠的功能,使用方式如下:

      class Product {
        /// 工廠構造函數(修飾 create 構造函數)
        factory Product.createFactory(int type) {
          if (type == 1) {
            return Product.product1;
          } else if (type == 2) {
            return Product._concrete2();
          }
          return Product._concrete();
        }
      
        /// 命名構造函數
        Product._concrete() : name = 'concrete';
      
        /// 命名構造函數1
        Product._concrete1() : name = 'concrete1';
      
        /// 命名構造函數2
        Product._concrete2() : name = 'concrete2';
      
        String name;
      }
      

      factory 修飾的構造函數需要返回一個當前類的對象實例,
      我們可以根據參數調用對應的構造函數,返回對應的對象實例。

      void main() {
        Product product = Product.createFactory(1);
        print(product.name); // concrete1
      }
      

      此外,工廠構造函數也并不要求我們每次都必須生成新的對象,
      我們也可以在類中預先定義一些對象供工廠構造函數使用,
      這樣每次在使用同樣的參數構建對象時,返回的會是同一個對象,
      單例模式 的章節中我們已經介紹過:

      class Product {
        /// 工廠構造函數
        factory Product.create(int type) {
          if (type == 1) {
            return product1;
          } else if (type == 2) {
            return product2();
          }
          return Product._concrete();
        }
      
        static final Product product1 = Product._concrete1();
        static final Product product2 = Product._concrete2();
      }
      

      factory 除了可以修飾命名構造函數外,也可以修飾默認的非命名構造函數,

      class Product {
        factory Product(int type) {
          return Product._concrete(); 
        }
      
        String? name;
      }
      

      到這里為止,工廠構造函數的一個缺點已經凸顯了出來,即使用者并不能直觀的感覺到自己正在使用的是工廠函數。
      工廠構造函數的使用方法和普通構造函數沒有區別,但這個構造函數生產的實例相當于是一種單例:

      void main() {
        Product product = Product(1);
        print(product.name); // concrete1
      }
      

      這樣的用法很容易造成使用者的困擾,因此,我們應當盡量使用特定的
      命名構造函數 作為工廠構造函數(如上面示例中的 createFactory)。

      工廠方法模式

      工廠方法模式同樣也是我們編程中最常用到的一種手段。

      抽象工廠 UML,圖源:refactoring.guru

      在簡單工廠中,它主要服務的對象是客戶,而 工廠方法 的使用者與工廠本身的類并不相干,
      而工廠方法模式主要服務自身的父類,如下的 ProductFactory(類比 UML 中的 Creator):

      /// 抽象工廠
      abstract class ProductFactory {
        /// 抽象工廠方法
        Product factoryMethod();
      
        /// 業務代碼
        void dosomthing() {
          Product product = factoryMethod();
          print(product.name);
        }
      }
      

      ProductFactory 類中,工廠方法 factoryMethod 是抽象方法,
      每個子類都必須重寫這個方法并返回對應不同的 Product 對象,
      dosomthing() 方法被調用時,就可以根據返回的對象做出不同的響應。
      具體使用方法如下:

      /// 具體工廠
      class ProductFactory1 extends ProductFactory {
        
        /// 具體工廠方法1
        @override
        Product factoryMethod() {
          return ConcreteProduct1();
        }
      }
      
      class ProductFactory2 extends ProductFactory {
        /// 具體工廠方法2
        @override
        Product factoryMethod() {
          return ConcreteProduct2();
        }
      }
      
      /// 使用
      main() {
        ProductFactory product = ProductFactory1();
        product.dosomthing();	// ConcreteProduct1
      }
      

      在 Flutter 中,抽象方法有一個非常實用的應用場景。我們在使用 Flutter 開發多端應用時通常需要考慮到多平臺的適配,即在多個平臺中,同樣的操作有時會產生不同的結果/樣式,我們可以將這些不同結果/樣式生成的邏輯放在工廠方法中。

      如下,我們定義一個 DialogFacory,用作生成不同樣式 Dialog 的工廠:

      abstract class DialogFacory {
        Widget createDialog(BuildContext context);
      
        Future<void> show(BuildContext context) async {
          final dialog = createDialog(context);
          return showDialog<void>(
            context: context,
            builder: (_) {
              return dialog;
            },
          );
        }
      }
      

      然后,針對 Android 和 iOS 兩個平臺,就可以創建兩個不同樣式的 Dialog 了:

      /// Android 平臺
      class AndroidAlertDialog extends DialogFactory {
      
        @override
        Widget createDialog(BuildContext context) {
          return AlertDialog(
            title: Text(getTitle()),
            content: const Text('This is the material-style alert dialog!'),
            actions: <Widget>[
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('Close'),
              ),
            ],
          );
        }
      }
      /// iOS 平臺
      class IOSAlertDialog extends DialogFactory {
        
        @override
        Widget createDialog(BuildContext context) {
          return CupertinoAlertDialog(
            title: Text(getTitle()),
            content: const Text('This is the cupertino-style alert dialog!'),
            actions: <Widget>[
              CupertinoButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('Close'),
              ),
            ],
          );
        }
      }
      

      現在,我們就可以像這樣使用對應的 Dialog 了:

      Future _showCustomDialog(BuildContext context) async {
        final dialog = AndroidAlertDialog();
        // final dialog = IOSAlertDialog();
        await selectedDialog.show(context);
      }
      

      抽象工廠

      抽象工廠模式,相較于 簡單工廠工廠方法 最大的不同是:這兩種模式只生產一種對象,而抽象工廠生產的是一系列對象(對象族),而且生成的這一系列對象一定存在某種聯系。比如 Apple 會生產 手機平板 等多個產品,這些產品都屬于 Apple 這個品牌。

      如下面這個抽象的工廠類:

      abstract class ElectronicProductFactory {
        Product createComputer();
        
        Product createMobile();
      
        Product createPad();
        
        // ...
      }
      

      對于 Apple 來說,我就是生產這類電子產品的工廠,于是可以繼承這個類,實現其中的方法生產各類產品:

      class Apple extends ElectronicProductFactory {
      
        @override
        Product createComputer() {
          return Mac();
        }
      
        @override
        Product createMobile() {
          return IPhone();
        }
      
        @override
        Product createPad() {
          return IPad();
        }
        
        // ...
      }
      

      同樣地,對于華為、小米等電子產品廠商也可以使用相同的方式表示,這就是抽象工廠模式。

      在開發 Flutter 應用中,我們也可以充分利用抽象工廠模式做切合應用的適配,我們可以定義如下這個抽象工廠,用于生產 widget:

      abstract class IWidgetsFactory {
        
        Widget createButton(BuildContext context);
        
        Widget createDialog(BuildContext context);
        
        // ...
      }
      

      我們的應用通常需要針對各個平臺展示不同風格的 widget。因此針對每一個平臺,我們都可以實現對應的實現工廠,如下:

      /// Material 風格組件工廠
      class MaterialWidgetsFactory extends IWidgetsFactory {
        @override
        Widget createButton(
            BuildContext context, VoidCallback? onPressed, String text) {
          return ElevatedButton(
            child: Text(text),
            onPressed: onPressed,
          );
        }
      
        @override
        Widget createDialog(BuildContext context, String title, String content) {
          return AlertDialog(title: Text(title), content: Text(content));
        }
        
        /// ...
      }
      
      /// Cupertino 風格組件工廠
      class CupertinoWidgetsFactory extends IWidgetsFactory {
        @override
        Widget createButton(
          BuildContext context,
          VoidCallback? onPressed,
          String text,
        ) {
          return CupertinoButton(
            child: Text(text),
            onPressed: onPressed,
          );
        }
      
        @override
        Widget createDialog(BuildContext context, String title, String content) {
          return CupertinoAlertDialog(
            title: Text(title),
            content: Text(content),
          );
        }
        
        // ...
      }
      

      這樣,在 Android 平臺上我們使用 MaterialWidgetsFactory,在 iOS 平臺上使用 CupertinoWidgetsFactory,就能使用對應平臺的 widget,想要適配更多平臺只需要再繼承 IWidgetsFactory 實現對應平臺的工廠類即可。

      至此,我們可以發現,作為創建型模式,這三類工廠模式主要工作就是以不同的方式創建對象,但他們各有特點:簡單工廠模式抽象的是 生產對象,工廠方法模式抽象的是 類方法,工廠方法模式抽象的則是 生產對象的工廠,如何使用就見仁見智了。

      拓展閱讀

      關于本系列文章

      Flutter / Dart 設計模式從南到北(簡稱 Flutter 設計模式)系列內容預計兩周發布一篇,著重向開發者介紹 Flutter 應用開發中常見的設計模式以及開發方式,旨在推進 Flutter / Dart 語言特性的普及,以及幫助開發者更高效地開發出高質量、可維護的 Flutter 應用。

      我很樂意繼續完善本系列中的文章,如果您對本文還有任何疑問或者文章的建議,歡迎向中文社區官方 Github 倉庫提交 issue 或者直接與我聯系,我會及時回復。

      posted on 2022-03-08 15:25  Flutter社區  閱讀(878)  評論(0)    收藏  舉報

      導航

      主站蜘蛛池模板: 老熟妇乱子交视频一区| 97在线碰| 边添小泬边狠狠躁视频| 亚洲欧洲一区二区天堂久久| 性欧美VIDEOFREE高清大喷水| 亚洲国产亚洲综合在线尤物| 亚洲欧美人成人综合在线播放 | 西昌市| 人妻一本久道久久综合鬼色 | 中文字幕一区二区人妻| 中年国产丰满熟女乱子正在播放| 国产妇女馒头高清泬20p多| 国产乱对白刺激视频| 美女自卫慰黄网站| 国产精品护士| 国日韩精品一区二区三区| 性欧美VIDEOFREE高清大喷水| 午夜福制92视频| 男人用嘴添女人私密视频| 四虎影视永久无码精品| 少妇愉情理伦片高潮日本| 香港特级三A毛片免费观看| 国产欧美日韩精品丝袜高跟鞋| 在线看av一区二区三区| 蜜桃一区二区三区免费看| 在线视频中文字幕二区| 亚洲国产aⅴ成人精品无吗| 九九热精品免费视频| 日韩不卡手机视频在线观看| 国模精品视频一区二区三区| 宝贝腿开大点我添添公视频免| 免费AV片在线观看网址| 免费观看的av在线播放| 欧美国产日韩久久mv| 一区二区丝袜美腿视频| 色av综合av综合无码网站| 亚洲偷自拍另类一区二区| 99久久国产成人免费网站| 无码射肉在线播放视频| 好看的国产精品自拍视频| 午夜性色一区二区三区不卡视频|