• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            alex

            alex

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              7 隨筆 :: 6 文章 :: 7 評論 :: 0 Trackbacks

            abstract factory.感覺是個很玄的名字,即使在我寫學習筆記的時候,我也因為缺少現實中的實踐而對其了解不深。^^希望.... 多指正
            Name:
            ?? abstract factory
            Addressed Problem:
            ?? 提供對同1種相關對象的創建。比如在程序里面,希望根據用戶配置來設置UI方案,比如方案1和2,對應的UI也存在2套不同的實現類,比如對于ScrollBar,有CScrollBar1和CScrollBar2,都繼承自ScrollBar。也許在程序里面有很多這樣的類。這樣你在應用UI實例化類時就必須要選擇比如
            IScrollBar* pScrollBar = NULL;
            if (_use_ui_1)
            ?? pScrollBar = new CScrollBar1;
            else
            ?? pScrollBar = new CScrollBar2;
            也許你這樣感覺沒多大關系,但想象下,在程序的多處都存在這樣的選擇,為什么我不選擇一種less error phone的方法呢?比如
            pScrollBar = Create(...);
            這樣一種簡單的方式呢?而且上面的寫法也引進了1個避短,也就是在產生pScrollBar時,涉及到了具體的實現類,這在面向對象這種program to interface這樣的語言中是很忌諱的事情。比如,在加種UI方案,也許你會再寫個else,這樣等于自己把自己往火堆里面推。你是一個勤奮的程序員,但不是個優秀的程序員^^.也許有人會說,我可以利用prototype這樣的方式來啊。這樣,在程序的外面配置一下每個類的prototype就可以了,或許也可以用object factory啊,都可以(^^似乎是哦,我也沒學過這2個的說)解決上面的問題,一個通過DoClone類似的,1個通過ID或其他的,其實在應用上面的2種時,自然的導出了abstract factory.為什么呢,因為上面的2種,你都需要設置多個的原型或ID。比如也許在CUIManager的構造里面寫賊大的if
            if (_use_ui_1)
            {
            ??? ...//設置UI_1下所有的prototype
            }
            else
            {
            ??? ...//設置UI_2下所有的prototype
            }
            也許在將來的莫天,在加上UI_3,則。再寫個if.也許大家可能會想,我在應用ui時,我就知道了所要創建的對象,為什么我不把上面寶裝一下改成:
            if (_use_ui_1)
            ?//設置factory_1
            else
            ?//設置factory_2
            然后在抽象出來的IFactory里面提供創建這些UI Class的方法,比如,CreateScrollBase.等等,這樣就有了abstract factory 的雛形。
            基礎實現
            /*
            ?測試abstract factory模式
            */

            class?IScrollWindow
            {
            public:
            ?virtual void?DrawScroll(void) = 0;
            };

            class?IListWindow
            {
            public:
            ?virtual?void?DrawList(void) = 0;
            };

            class?ICreateWindowFactory
            {
            public:
            ?virtual?IScrollWindow*?CreateScrollWindow(void) = 0;

            ?virtual?IListWindow*?CreateListWindow(void) = 0;
            };

            class?CBlueWindowFactory:
            ?public?ICreateWindowFactory
            {
            ?class?CBlueScrollWindow:
            ??public?IScrollWindow
            ?{
            ?public:
            ??virtual void?DrawScroll(void)
            ??{
            ???std::cout << "draw blue scroll" << std::endl;
            ??}
            ?};

            ?class?CBlueListWindow:
            ??public?IListWindow
            ?{
            ?public:
            ??virtual?void?DrawList(void)
            ??{
            ???std::cout << "draw blue list" << std::endl;
            ??}
            ?};
            public:
            ?virtual?IScrollWindow*?CreateScrollWindow(void)
            ?{
            ??return?new CBlueScrollWindow;
            ?}

            ?virtual?IListWindow*?CreateListWindow(void)
            ?{
            ??return?new CBlueListWindow;
            ?}
            };

            class?CRedWindowFactory:
            ?public?ICreateWindowFactory
            {
            ?class?CRedScrollWindow:
            ??public?IScrollWindow
            ?{
            ?public:
            ??virtual void?DrawScroll(void)
            ??{
            ???std::cout << "draw red scroll" << std::endl;
            ??}
            ?};

            ?class?CRedListWindow:
            ??public?IListWindow
            ?{
            ?public:
            ??virtual?void?DrawList(void)
            ??{
            ???std::cout << "draw red list" << std::endl;
            ??}
            ?};
            public:
            ?virtual?IScrollWindow*?CreateScrollWindow(void)
            ?{
            ??return?new CRedScrollWindow;
            ?}

            ?virtual?IListWindow*?CreateListWindow(void)
            ?{
            ??return?new CRedListWindow;
            ?}
            };
            在需要用的地方,就可以這樣:
            ICreateWindowFactory*?pCreateWindow1?= new CBlueWindowFactory;

            ?pCreateWindow1->CreateListWindow()->DrawList();
            ?pCreateWindow1->CreateScrollWindow()->DrawScroll();
            假如需要用不同的工廠,則更換不會影響到調用處的代碼。因為掉用工廠的地方是面向接口的。其實abstract factory的理念應該是比較簡單的(^^瞎猜的).基本講完了什么是抽象類工廠,他要解決的一些問題以及怎么解決和1個小而亂的demo代碼段。下面來看下我們怎么泛化這個類工廠,這個會涉及到loki里面的具體實現,大家要加滿油啊,因為泛化類工廠是一件不容易的事情啊。

            泛化_1
            首先,(^^這部分我也不是很懂)要泛化的是abstract factory的接口,就象上面的CreateScrollWindow和CreateListWindow,在泛化時需要的信息是要創建的同1組對象的相關接口比如IScrollBar,IList等等,在loki里面,要為1個類泛化1組接口,可以通過GenScatterHierarchy來將unit應用到typelist里的每1個類型,并將該類從unit<type>派生,從而得到1組接口。GenScatterHierarchy做了什么呢,他產生了啥呢?具體的可以看morden c++里面的實現。通過GenScatterHierarchy我們得到了我們要得1組接口。下面是loki里面對這個得相關實現
            template <class T>
            class AbstractFactoryUnit
            {
            public:
            ????virtual T* DoCreate(Type2Type<T>) = 0;
            ????virtual ~AbstractFactoryUnit() {}
            };

            可以看到,上面定義了2個函數,而這個類就是我上面說得調用GenScatterHierarchy時,具現化時對typelist得每個類型應用得template類,而最后產生得也將是類似AbstractFactoryUnit<IScrollBar>的類,我們具體的抽象工廠從這些派生。至于pure dctor這個大家應該都知道啥作用。下面來看Abstract Factory 的泛化:

            template
            <
            ????class TList,
            ????template <class> class Unit = AbstractFactoryUnit
            >
            class AbstractFactory : public GenScatterHierarchy<TList, Unit>
            {
            public:
            ?????typedef TList ProductList;
            ???????
            ?????template <class T> T* Create()
            ?????{
            ????????Unit<T>& unit = *this;
            ????????return unit.DoCreate(Type2Type<T>());
            ?????}
            ?};
            可以看到這個即由GenScatterHierarchy來得到了我們想要的東西。提供了Create的模板函數,使得我們可以象這樣factory.Create<IScrollBar>()的方便形勢來調用。ProductList是對于抽象工廠要創建的類型的重命名。方便后面在產生實際的類型時,獲取對應的類型信息,對于DoCreate的參數,大家應該都明白這是重載用的,那用在哪里呢?下面會介紹。

            泛化_2
            在辛苦介紹完泛化抽象工廠的接口后,我們可以通過類似的方式來定義1個abstract factory的接口
            Loki::AbstractFactory<LOKI_TYPELIST_2(IScrollBar,IListWindow)>
            下面我們來介紹最后的,我們怎么來提供抽象工廠的實現,首先是對象的創建,loki里面提供了默認的創建的方法,當然我們可以修改或用特化的版本來做選擇。
            template <class ConcreteProduct, class Base>
            class OpNewFactoryUnit : public Base
            {
            ???? typedef typename Base::ProductList BaseProductList;
            ???
            protected:
            ?????typedef typename BaseProductList::Tail ProductList;
            ???
            public:
            ?????typedef typename BaseProductList::Head AbstractProduct;
            ?????ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
            ?????{
            ????????? return new ConcreteProduct;
            ?????}
            };
            可以看到DoCreate是我們的核心部分,里面調用了new來創建對象。而這里也讓我們看到這應該是上面創建對象的重載。而Type2Type的作用正是在這里體現作用,因為c++無法通過函數返回值來重載不同的對象。也許你會看到上面的一些類型定義,包括OpNewFactoryUnit的2個模板參數,第2個模板參數是實現GenLinearHierarchy必備的GenLinearHierarchy和上面的GenScatterHierarchy的核心思想一樣,都是通過具現化來實現的,不過GenLinearHierarchy產生的是線性的繼承體系,中間夾雜著比如OpNewFactoryUnit<IScrollBar,GenLinearHierarchy<...> >這樣的形勢。下面來看下抽象工程的具體實現的泛化,聯系起來就能對上面的理解了
            template
            <
            ????class AbstractFact,
            ????template <class, class> class Creator = OpNewFactoryUnit,
            ????class TList = typename AbstractFact::ProductList
            >
            class ConcreteFactory
            ?????: public GenLinearHierarchy<
            ?????typename TL::Reverse<TList>::Result, Creator, AbstractFact>
            {
            public:
            ????typedef typename AbstractFact::ProductList ProductList;
            ????typedef TList ConcreteProductList;
            };
            可以看到ConcreteFactory由GenLinearHierarchy來驅動產生我們想要的,本來這個貼圖比較明朗點,但我懶的畫,哈哈。從GenLinearHierarchy的參數來看,第1個是具體的實現類的typelist,比如LOKI_TYPELIST2(CScrollBar_1,CListWindow_1),至于為什么要對類型做reverse操作,因為在類的基礎體系產生后,typelist的第1個元素,在繼承體系是由下往上的,而于上面由OpNewFactoryUnit等定義的ProductList的Head定義的自上往下的是相反的,所以這里應用了reverse操作。Creator就是上面的OpNewFactoryUnit或你自定義的元素。并在具現化是,應用typelist的每個類型。AbstractFact是繼承體現的最頂端,這個應該很明顯,就是上面定義的AbstractFactory,這樣啥都明確了,具體的接口,對接口的函數的重載都已經泛化完成。下面是(^^睡死了,睡覺去了,簡單從便,上面均未調試哦).至于為什么會把第3個參數默認為抽象類工廠接口的ProductList,這個和loki用基于prototype的Creator有關系。。(^^俺是菜鳥,就只能到這里了)
            對abstract factory的看法,優點在上面的已經說過了,確定在,我們要添加1種對象的創建時,都要去修改接口的定義,當然后面的泛化也為我們解決了些問題,但泛化對于參數的傳遞不怎么好用,可以通過提供新的OpNewFactoryUnit來適當解決。
            ??????????????????????????????????????????????????? agerlis.2007.2.10 0:22
            posted on 2007-02-11 15:53 agerlis 閱讀(383) 評論(0)  編輯 收藏 引用
            人妻久久久一区二区三区| 久久A级毛片免费观看| 国产精品VIDEOSSEX久久发布| 欧洲精品久久久av无码电影 | 久久亚洲欧美日本精品| 国内精品久久久久影院亚洲| 久久精品国产亚洲一区二区三区| 久久无码AV中文出轨人妻| 无码精品久久一区二区三区| 亚洲人成无码久久电影网站| 久久香综合精品久久伊人| 亚洲精品白浆高清久久久久久| 久久久噜噜噜久久中文福利| 99久久精品国内| 久久一区二区三区99| 久久精品亚洲男人的天堂| 伊人久久大香线蕉精品不卡| 午夜欧美精品久久久久久久| 久久国产精品久久| 久久久午夜精品福利内容| 久久精品国产99国产电影网| 国产精品一区二区久久精品无码 | 欧美久久亚洲精品| 久久91精品综合国产首页| 一本大道久久香蕉成人网| 国产精品久久国产精品99盘| 久久久久国产成人精品亚洲午夜| 中文精品久久久久人妻不卡| 久久成人18免费网站| 欧洲成人午夜精品无码区久久 | 久久久久四虎国产精品| 亚洲精品午夜国产VA久久成人| 国产免费福利体检区久久| 亚洲AV日韩精品久久久久| 亚洲欧洲精品成人久久奇米网| 伊人久久国产免费观看视频| 亚洲欧美日韩精品久久| 一本一道久久a久久精品综合| 久久久久亚洲av综合波多野结衣| 久久久99精品一区二区| 日韩欧美亚洲综合久久影院d3|