• <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 閱讀(1719) 評論(0)  編輯 收藏 引用 所屬分類: C++
            久久无码AV中文出轨人妻| www.久久99| 久久午夜福利电影| 久久久久国产精品人妻| 久久精品国产亚洲av水果派| 久久久精品午夜免费不卡| 91精品观看91久久久久久| 欧美日韩中文字幕久久久不卡 | 亚洲精品乱码久久久久66| 99久久国产综合精品女同图片| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 久久精品国产亚洲av水果派| av无码久久久久久不卡网站| 国产999精品久久久久久| 99精品国产综合久久久久五月天| 51久久夜色精品国产| 亚洲国产精品18久久久久久| 中文国产成人精品久久亚洲精品AⅤ无码精品| 久久国产精品波多野结衣AV| 久久不见久久见免费视频7| 久久综合成人网| 久久精品国产精品亚洲人人| 午夜不卡888久久| 精品久久人人爽天天玩人人妻| 久久精品国产亚洲网站| 久久亚洲综合色一区二区三区| 久久午夜羞羞影院免费观看| 老司机国内精品久久久久| 伊人久久大香线焦综合四虎| 久久96国产精品久久久| 99久久亚洲综合精品网站| 丁香久久婷婷国产午夜视频| 亚洲AV伊人久久青青草原| 欧洲成人午夜精品无码区久久| 欧美精品久久久久久久自慰| 2020最新久久久视精品爱| 亚洲国产成人久久一区WWW| 2020国产成人久久精品| 伊人久久大香线焦AV综合影院| 久久久久AV综合网成人| 伊人久久大香线蕉综合网站|