• <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>

            小明思考

            高性能服務(wù)器端計(jì)算
            posts - 70, comments - 428, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            從全局變量到IOC模式

            Posted on 2006-01-20 17:23 小明 閱讀(4948) 評(píng)論(7)  編輯 收藏 引用 所屬分類(lèi): C/C++
            很早以前,在我初學(xué)c語(yǔ)言的時(shí)候,我的第一個(gè)象樣的程序是一個(gè)五子棋程序,使用了TC2.0的圖形庫(kù),純面向過(guò)程的設(shè)計(jì),由上到下的設(shè)計(jì),而且只有一個(gè)c文件就搞定了,大概幾百行,可惜代碼已經(jīng)失傳,非常可惜。

            為什么要全局變量?
            List 1
            int main()
            {
            int s1,s2,s3;
            fun1(s1);
            fun2(s1,s2);
            fun3(s1,s2,s3);
            return 0;
            }
            上面的s1,s2,s3如果改成全局變量,則變?yōu)?BR>List 2
            int s1,s2,s3;

            int main()
            {
                fun1();
                fun2();
                fun3();
            }
            似乎簡(jiǎn)潔了一些,而且沒(méi)有了傳遞參數(shù)的開(kāi)銷(xiāo)。但是缺點(diǎn)也是很明顯的,帶了三個(gè)函數(shù)之間的耦合。

            既然我們認(rèn)識(shí)到全局變量的問(wèn)題,怎么改進(jìn)呢?
            代碼1中由于有三個(gè)變量,如果有更多的,就更麻煩,我們可以這樣改進(jìn)
            List 3
            typedef struct statusTag
            {
                
            int s1,s2,s3;
            }Status;

            int main()
            {
                Status s;
                fun1(
            &s);
                fun2(
            &s);
                fun3(
            &s);
                
            return 0;
            }
            這種技巧你可以在lua中看到,看lua的使用代碼
            List4
            #include "lua.h"
            #include 
            "lauxlib.h"
            #include 
            "lualib.h"

            int main(int argc, char *argv[])
            {
                lua_State 
            *= lua_open();
                
            const char *buf = "var = 100";
                
            int var ;
                luaopen_base(L);
                luaopen_io(L);
                lua_dostring(L, buf);
                lua_getglobal(L, 
            "var");
                var 
            = lua_tonumber(L, -1);
                lua_close(L);
                
                
            return 0;
            請(qǐng)注意到這里的lua_open方法,這其實(shí)是一種創(chuàng)建自己的工廠方法。不使用全局變量的好處就是,我們保留了可以創(chuàng)建多個(gè)對(duì)象的自由。

            時(shí)代在發(fā)展,進(jìn)入C++時(shí)代,但是全局變量仍然有人在用,存在就是合理的。GOF提出一種設(shè)計(jì)模式叫Singleton的模式,其核心思想就是不讓全局變量漂浮在空中,把它放入class中,成為衣冠楚楚的C++公民。著名的Meyer Singleton像這樣
            List 5
            class Status
            {
            private:
                Status(){};
            public:
                
            static Status& getInstance()
                {
                       
            static Status s;
                       
            return s;
                }
            };

            class User
            {
                
            void fun()
                {
                    Status 
            &= Status::Instance();
                    
            //. . .use s
                }
            };

            一切似乎很完美,使用private來(lái)防止client 創(chuàng)建它,保證了對(duì)象的唯一性(注意:Meyer singleton并不具有多線程安全,可能導(dǎo)致多次初始化對(duì)象)

            但是隨著 針對(duì)接口編程和單元測(cè)試越來(lái)越流行,singleton帶來(lái)的對(duì)單元測(cè)試不友好的特點(diǎn)日益體現(xiàn),全局變量不能很好的被mock,所以難于測(cè)試。

            這時(shí)候所謂的IOC思想(Inversion of Control,即反轉(zhuǎn)模式)出來(lái)了,簡(jiǎn)單的來(lái)說(shuō),就是通過(guò)構(gòu)造函數(shù)或者set方法實(shí)現(xiàn)注入

            List6 - 構(gòu)造函數(shù)注入
            class Status{};

            class User
            {
               
            public:
                  User(Status 
            *s):m_ps(s){};
                  
            void fun()
                  {
                       Status 
            *= m_ps;
                  }
               
            private:
                  Status 
            *m_ps;
            }

            List7 - Set 注入
            class Status{};

            class User
            {
               
            public:
                  User(){}
                  
                  
            void setStaus(Status *s)
                  {
                       m_ps 
            = s;
                  }
                  
                  
            void fun()
                  {
                       Status 
            *= m_ps;
                  }
               
            private:
                  Status 
            *m_ps;
            }

            使用IOC的好處是帶來(lái)了更強(qiáng)大的靈活性,但是帶來(lái)的問(wèn)題就是調(diào)用者麻煩了(天下沒(méi)有免費(fèi)的午餐阿)

            List8
            int main()
            {
               Status s;
               User u;
               u.setStatus(
            &s);
               u.fun();
               
            return 0;
            }

            好像一切又返樸歸真,似乎并沒(méi)有帶來(lái)什么簡(jiǎn)單。有的時(shí)候簡(jiǎn)單和靈活性就是死對(duì)頭。

            為了簡(jiǎn)化用戶(hù)進(jìn)行手工注入,IOC容器出現(xiàn),在Java世界里面,最著名的莫過(guò)于Spring了.IOC容器就像一個(gè)巨大的創(chuàng)建工廠,她可以使用xml來(lái)配置這些,這真的是一場(chǎng)革命。

            <beans>
                
            <bean id="status" class="Status">
                
            </bean>

                
            <bean id="user" class="User">
                    
            <property name="status"><ref bean="status"/></property>
                
            </bean>
            </beans>
            Spring就是這樣把注入的工作移到配置文件中去,提供了強(qiáng)大的靈活性和可配置性


            但是由于c/c++ 不具備的java那么多運(yùn)行期的類(lèi)型識(shí)別和反射的功能,所以我目前還沒(méi)有發(fā)現(xiàn)有在C++中使用的IOC容器,如果你知道,請(qǐng)告訴我

            那么如果是C++怎么來(lái)使注入變得簡(jiǎn)單一點(diǎn)呢,可以使用工廠方法了

            List9
            User * createUser(Status &s,Status2 &s2)
            {
               User 
            *user = new User();
               user
            ->setStatus(s);
               user
            ->setStatus2(s2);
               
            return user;
            }


            總結(jié):
            其實(shí)軟件的設(shè)計(jì)根本就沒(méi)有所謂的黃金法則,沒(méi)有免費(fèi)的午餐,你在獲得更強(qiáng)大的靈活性,往往都得到復(fù)雜性的附加效果。如果你就是寫(xiě)一個(gè)自己玩的小游戲,ok,你就是用全局變量。如果你要設(shè)計(jì)龐大的Office,那你就沒(méi)有辦法把代碼寫(xiě)的很簡(jiǎn)單,因?yàn)槟阋紤]的東西多了,可維護(hù)性,可測(cè)試性。

            Feedback

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2006-02-11 16:24 by 3×7=51
            文章寫(xiě)得不錯(cuò),cppblog首頁(yè)上的大部分文章如果都能象這篇文章這樣言之有物就好了。

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2006-03-13 22:02 by fiestay
            真的很不錯(cuò),希望能看到更多精彩文章:)

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2006-05-17 10:12 by Roger
            寫(xiě)得不錯(cuò)
            不過(guò)spring用xml來(lái)配置帶來(lái)了一個(gè)不方便的地方,就是沒(méi)辦法進(jìn)行重構(gòu),xml hell.

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2008-01-11 10:40 by thh
            http://code.google.com/p/pococapsule/

            c++ 的ioc,我也是剛剛看到

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2009-02-13 16:20 by aztack
            好文

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2009-03-31 11:10 by 1234
            看上去有點(diǎn)意思,但實(shí)際上完全沒(méi)講到點(diǎn)子上

            依賴(lài)注入、控制反轉(zhuǎn)~
            什么是依賴(lài)?誰(shuí)依賴(lài)誰(shuí)?如何注入?
            什么是控制?誰(shuí)控制誰(shuí)?為何稱(chēng)為反轉(zhuǎn)?

            請(qǐng)找經(jīng)典文章仔細(xì)研究

            # re: 從全局變量到IOC模式  回復(fù)  更多評(píng)論   

            2009-09-17 14:37 by tom zhou
            PocoCapsule/C++ IoC and DSM Framework
            日本久久久久久久久久| 超级碰碰碰碰97久久久久| 伊人伊成久久人综合网777| 久久99精品国产一区二区三区| 久久狠狠爱亚洲综合影院| 亚洲伊人久久大香线蕉苏妲己| 国产成人精品久久一区二区三区| 精品一二三区久久aaa片| 久久无码中文字幕东京热| 久久久久久国产精品美女| 日本道色综合久久影院| 狠狠久久亚洲欧美专区| 久久夜色tv网站| 国产精品一区二区久久精品无码| 国产伊人久久| 久久伊人色| 伊人久久综合精品无码AV专区| 久久九九兔免费精品6| 亚洲AV日韩精品久久久久久| 无码国产69精品久久久久网站| 久久丫精品国产亚洲av| 久久免费精品一区二区| 国产精品免费久久久久久久久 | 国内精品九九久久精品| 久久精品亚洲一区二区三区浴池 | 色欲久久久天天天综合网精品 | 狠狠色丁香久久婷婷综合_中 | 久久久久久精品免费看SSS| 久久综合精品国产二区无码| 日产精品久久久久久久性色| 亚洲女久久久噜噜噜熟女| 91久久精一区二区三区大全| 久久精品国产第一区二区| 亚洲国产成人久久综合区| 久久婷婷五月综合国产尤物app| 久久综合狠狠色综合伊人| 亚洲国产日韩欧美久久| 久久99国内精品自在现线| 久久影院久久香蕉国产线看观看| 99久久国产亚洲综合精品| 色噜噜狠狠先锋影音久久|