• <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的學習園地

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

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

            有了這個特性,就可以實現一些模式了,這里列出AOP中經典的觀察者(Observer)模式[注]

            [注]這個說法不太妥當,觀察者模式是經典的設計模式,這里的意思是說AOP經典的觀察者模式實現。

            它的代碼如下:

            aspect ObserverPattern {
                
            // 管理subjects和observers的數據結構
                
            // 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 ());
                
            // 為每個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++實現代碼,可以簡單實現一個:
            #ifndef __OBSERVER_PATTERN_AH__
            #define __OBSERVER_PATTERN_AH__

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

            aspect ObserverPattern {
                
            // 管理subjects和observers的數據結構
                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 ());
                
            // 為每個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供下面使用。

            下面編寫一個應用實例:

            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(這個用來測試Aspect C++的匹配模式會不會混亂)
            #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;
            }

            這個程序編譯運行,沒有任何輸出。有時候為了監視對象的狀態,可以在執行一個操作后加上一些打印狀態的代碼,當然這樣比較繁瑣;也可以在各個操作函數中加入這些代碼,但修改已經寫好的代碼總是不太舒服。

            下面先實現一個Car狀態打印類:

            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__

            這個方面重寫了subjects以及observers切面,并定義了observers在update被調用時執行的操作,另外還在Car的構造函數和析構函數中添加了注冊和注銷代碼。

            運行ac++生成代碼,編譯并運行,結果如下:

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

            關于Aspect C++以及AOP,還有許多話題,不過不打算再繼續了,AOP是個廣泛的議題,局限在某一實現上只會使我們眼界變窄。

            AOP被稱為設計模式最佳實踐者,它當之無愧。網上還有很多AOP實踐設計模式的資料。
            posted on 2005-12-17 10:21 qiezi 閱讀(1707) 評論(0)  編輯 收藏 引用 所屬分類: C++
            久久久久久精品无码人妻| 国产免费久久久久久无码| 久久精品综合网| 国产成人无码精品久久久性色| 色妞色综合久久夜夜| 日本强好片久久久久久AAA| 国内精品久久久久影院免费| 狠狠人妻久久久久久综合蜜桃| 欧美伊人久久大香线蕉综合69| 性做久久久久久久久浪潮| 久久综合给合久久国产免费 | 久久久久久国产精品美女| 久久一区二区免费播放| 丰满少妇高潮惨叫久久久| 三级片免费观看久久| 精品久久久久久成人AV| 亚洲精品乱码久久久久久不卡| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 亚洲国产成人精品91久久久 | 日日狠狠久久偷偷色综合96蜜桃 | 国产精品久久久久AV福利动漫 | 久久亚洲日韩精品一区二区三区| 国产精品九九久久免费视频 | 久久精品国产亚洲5555| 国产91色综合久久免费| 色青青草原桃花久久综合| 国产精品伦理久久久久久| 久久精品www人人爽人人| 亚洲国产精品无码久久青草| 天天爽天天爽天天片a久久网| 久久久国产打桩机| 午夜精品久久久久9999高清| 精品久久久久久99人妻| 天天爽天天爽天天片a久久网| 色婷婷久久综合中文久久蜜桃av | 久久亚洲电影| 国产精品欧美久久久久无广告| 97久久国产亚洲精品超碰热| 久久久婷婷五月亚洲97号色| 日韩人妻无码精品久久免费一| 欧美国产成人久久精品|