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

            qiezi的學(xué)習(xí)園地

            AS/C/C++/D/Java/JS/Python/Ruby

              C++博客 :: 首頁(yè) :: 新隨筆 ::  ::  :: 管理 ::
            Aspect C++支持“虛切面”,類似C++中的虛函數(shù)。方面可以繼承,“派生方面”可以重寫“基方面”的“虛切面”,類似C++中的類繼承。

            有了這個(gè)特性,就可以實(shí)現(xiàn)一些模式了,這里列出AOP中經(jīng)典的觀察者(Observer)模式[注]

            [注]這個(gè)說(shuō)法不太妥當(dāng),觀察者模式是經(jīng)典的設(shè)計(jì)模式,這里的意思是說(shuō)AOP經(jīng)典的觀察者模式實(shí)現(xiàn)。

            它的代碼如下:

            aspect ObserverPattern {
                
            // 管理subjects和observers的數(shù)據(jù)結(jié)構(gòu)
                
            // TODO 
            public:
                
            // 角色接口
                struct ISubject {};
                
            struct IObserver {
                    
            virtual void update(ISubject *= 0;
                };
                
            // 在派生方面中被重寫
                pointcut virtual observers () = 0;
                pointcut 
            virtual subjects () = 0;
                
            // subjectChange()匹配所有非const方法,但限定了subjects類
                pointcut virtual subjectChange () =
                    execution(
            " % ::%(" && !" % ::%() const")
                    
            && within(subjects ());
                
            // 為每個(gè)subject/observer類增加基類,并插入通知代碼
                advice observers () : baseclass(IObserver );
                advice subjects () : baseclass(ISubject );
                advice subjectChange () : after() {
                    ISubject 
            * subject = tjp->that ();
                    updateObservers (subject );
                }
                
            // 具體操作
                void updateObservers (ISubject * sub ) {  }
                
            void addObserver (ISubject * sub , IObserver * ob ) {  }
                
            void remObserver (ISubject * sub , IObserver * ob ) {  }
            };

            其中“...” 部分是需要完成的C++實(shí)現(xiàn)代碼,可以簡(jiǎn)單實(shí)現(xiàn)一個(gè):
            #ifndef __OBSERVER_PATTERN_AH__
            #define __OBSERVER_PATTERN_AH__

            #include 
            <map>
            #include 
            <set>
            using namespace std;

            aspect ObserverPattern {
                
            // 管理subjects和observers的數(shù)據(jù)結(jié)構(gòu)
                struct ISubject;
                
            struct IObserver;
                map 
            < ISubject*set<IObserver*> > listeners;
            public:
                
            // 角色接口
                struct ISubject {};
                
            struct IObserver {
                    
            virtual void update(ISubject *= 0;
                };
                
            // 在派生方面中被重寫
                pointcut virtual observers () = 0;
                pointcut 
            virtual subjects () = 0;
                
            // subjectChange()匹配所有非const方法
                pointcut virtual subjectChange () =
                    execution(
            " % ::%(" && !" % ::%() const")
                    
            && within(subjects ());
                
            // 為每個(gè)subject/observer類增加基類,并插入通知代碼
                advice observers () : baseclass(IObserver );
                advice subjects () : baseclass(ISubject );
                advice subjectChange () : after() {
                    ISubject 
            * subject = tjp->that ();
                    updateObservers (subject );
                }
                
            // 具體操作
                void updateObservers (ISubject * sub ) {
                    
            const set<IObserver*>& observers = listeners[sub];
                    
            set<IObserver*>::const_iterator iter = observers.begin();
                    
            for (; iter != observers.end(); iter ++)
                    {
                        (
            *iter)->update(sub);
                    }
                }
                
            void addObserver (ISubject * sub , IObserver * ob ) { listeners[sub].insert(ob); }
                
            void removeObserver (ISubject * sub , IObserver * ob ) { listeners[sub].erase(ob); }
            };

            #endif // __OBSERVER_PATTERN_AH__

            保存為ObserverPattern.ah供下面使用。

            下面編寫一個(gè)應(yīng)用實(shí)例:

            1、car.h

            #ifndef __CAR_H__
            #define __CAR_H__

            #include 
            <string>
            using namespace std;

            class Car
            {
                
            string name;
                
            int x;
                
            int y;
                
            enum Direction{South, East, North, West};
                Direction direction;

                Car (
            const Car&);
                Car
            & operator = (const Car&);
            public:
                Car (
            const string& name);
                
            void turnLeft ();
                
            void turnRight ();
                
            void forward (size_t step);

                
            const string& getName() const;
                
            int getX () const;
                
            int getY () const;
                Direction getDirection () 
            const;
            };



            #endif // __CAR_H__


            2、car.cc

            #include 
            "car.h"
            #include 
            <cassert>

            Car::Car (
            const string& name_)
            : name(name_), x(
            0), y(0), direction(South)
            {
            }

            void Car::turnLeft ()
            {
                
            if (direction == West)
                    direction 
            = South;
                
            else
                    direction 
            = (Direction)(int(direction) + 1);
            }

            void Car::turnRight ()
            {
                
            if (direction == South)
                    direction 
            = West;
                
            else
                    direction 
            = (Direction)(int(direction) - 1);
            }

            void Car::forward (size_t step)
            {
                
            switch (direction)
                {
                
            case South:
                    y 
            += step; break;
                
            case East:
                    x 
            += step; break;
                
            case North:
                    y 
            -= step; break;
                
            case West:
                    x 
            -= step; break;
                
            default:
                    assert (
            !"Invalid direction");
                }
            }

            const string& Car::getName() const
            {
                
            return name;
            }

            int Car::getX() const
            {
                
            return x;
            }

            int Car::getY() const
            {
                
            return y;
            }

            Car::Direction Car::getDirection() 
            const
            {
                
            return direction;
            }

            3、dummy.h(這個(gè)用來(lái)測(cè)試Aspect C++的匹配模式會(huì)不會(huì)混亂)
            #ifndef __DUMMY_H__
            #define __DUMMY_H__

            class Dummy
            {
            public:
                
            void test_non_const (){}
                
            void test_const () const {}
            };

            #endif // __DUMMY_H__

            4、main.cc
            #include "car.h"
            #include 
            "dummy.h"

            int main()
            {
                Car car(
            "No.1");
                car.turnLeft();
                car.forward(
            3);
                car.turnLeft();
                car.forward(
            9);
                car.turnRight();
                car.forward(
            12);

                Car car1(
            "No.2");
                car1.forward(
            7);
                car1.turnLeft();
                car1.forward(
            3);

                car.forward(
            5);

                Dummy dummy;
                dummy.test_non_const();
                dummy.test_const();
                
                
            return 0;
            }

            這個(gè)程序編譯運(yùn)行,沒(méi)有任何輸出。有時(shí)候?yàn)榱吮O(jiān)視對(duì)象的狀態(tài),可以在執(zhí)行一個(gè)操作后加上一些打印狀態(tài)的代碼,當(dāng)然這樣比較繁瑣;也可以在各個(gè)操作函數(shù)中加入這些代碼,但修改已經(jīng)寫好的代碼總是不太舒服。

            下面先實(shí)現(xiàn)一個(gè)Car狀態(tài)打印類:

            5、car_logging.h
            #ifndef __CAR_LOGGING__
            #define __CAR_LOGGING__

            #include 
            "car.h"
            #include 
            <iostream>
            using namespace std;

            class CarLogging
            {
            public:
                
            void printCarInfo (const Car& car)
                {
                    
            static const char* direction_str[] = {"South""East""North""West"};
                    cout 
            << "Car name: " << car.getName()
                        
            << ", direction: " << direction_str[int(car.getDirection())] 
                        
            << ", x: " << car.getX() 
                        
            << ", y: " << car.getY() 
                        
            << endl;
                }
            };

            extern CarLogging g_carLogging;

            #endif // __CAR_LOGGING__

            6、car_logging.cc
            #include "car_logging.h"

            CarLogging g_carLogging;

            7、CarLoggingObserver.ah
            #ifndef __CAR_LOGGING_OBSERVER_AH__
            #define __CAR_LOGGING_OBSERVER_AH__

            #include 
            "ObserverPattern.ah"
            #include 
            "car.h"
            #include 
            "car_logging.h"

            aspect CarLoggingObserver : 
            public ObserverPattern {
                
            // 定義方面(ointcuts)
                pointcut subjects() = "Car";
                pointcut observers() 
            = "CarLogging";
            public:
                advice observers() :
                
            void update( ObserverPattern::ISubject* sub ) {
                    printCarInfo (
            *(Car*)sub);
                }

                advice construction (classes(subjects())) : after()
                {
                    addObserver(tjp
            ->that(), &g_carLogging);
                }

                advice destruction (classes(subjects())) : before()
                {
                    removeObserver(tjp
            ->that(), &g_carLogging);
                }
            };

            #endif // __CAR_LOGGING_OBSERVER_AH__

            這個(gè)方面重寫了subjects以及observers切面,并定義了observers在update被調(diào)用時(shí)執(zhí)行的操作,另外還在Car的構(gòu)造函數(shù)和析構(gòu)函數(shù)中添加了注冊(cè)和注銷代碼。

            運(yùn)行ac++生成代碼,編譯并運(yùn)行,結(jié)果如下:

            這里演示的例子依舊選擇了不影響原始程序的做法,網(wǎng)上很多資料都把這個(gè)模式和實(shí)現(xiàn)代碼結(jié)合起來(lái),由于Aspect C++編譯速度還是很慢,所以選擇“外掛”的方式,這樣不需要這些方面時(shí),直接編譯C++代碼即可。

            關(guān)于Aspect C++以及AOP,還有許多話題,不過(guò)不打算再繼續(xù)了,AOP是個(gè)廣泛的議題,局限在某一實(shí)現(xiàn)上只會(huì)使我們眼界變窄。

            AOP被稱為設(shè)計(jì)模式最佳實(shí)踐者,它當(dāng)之無(wú)愧。網(wǎng)上還有很多AOP實(shí)踐設(shè)計(jì)模式的資料。
            posted on 2005-12-17 10:21 qiezi 閱讀(1713) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++
            国产成人精品三上悠亚久久| 日韩人妻无码精品久久久不卡| 久久九色综合九色99伊人| 久久久青草青青国产亚洲免观| 亚洲综合久久久| 国产精品久久久久jk制服| 久久九九久精品国产| 热re99久久6国产精品免费| 国产91久久综合| 日韩人妻无码精品久久免费一| 99久久精品无码一区二区毛片| 伊人久久一区二区三区无码| 国产午夜福利精品久久2021| 性高朝久久久久久久久久| 久久不见久久见免费视频7| 午夜福利91久久福利| segui久久国产精品| 久久精品天天中文字幕人妻 | 伊人久久大香线蕉AV一区二区| 潮喷大喷水系列无码久久精品| 伊人久久国产免费观看视频| 伊人久久大香线蕉精品| 久久精品国产亚洲AV高清热| 久久受www免费人成_看片中文| 国产精品成人久久久久久久| 精品永久久福利一区二区 | 国产精品九九九久久九九| 波多野结衣久久精品| 久久伊人色| 亚洲一级Av无码毛片久久精品| 国产精品狼人久久久久影院| 狠狠色丁香婷综合久久| 久久人人爽人人爽人人片AV不 | 国产福利电影一区二区三区,免费久久久久久久精 | 久久青草国产精品一区| 国产午夜福利精品久久2021| 亚洲精品美女久久777777| 久久精品国产免费观看| 久久精品免费一区二区| 午夜久久久久久禁播电影| 亚洲中文字幕无码一久久区|