- 浏览: 497241 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hypercube:
markin'
配置D语言编程环境 -
qiezi:
qiezi 写道yangyang_08 写道1 ...
我的编程语言学习经历 -
qiezi:
yangyang_08 写道1、现在如果做并发服务器,楼主选用 ...
我的编程语言学习经历 -
yangyang_08:
1、现在如果做并发服务器,楼主选用什么样的语言架构?2、lua ...
我的编程语言学习经历 -
dearplain:
我也是语言爱好者,不过我一直坚持使用c。
我的编程语言学习经历
Aspect C++支持“虚切面”,类似C++中的虚函数。方面可以继承,“派生方面”可以重写“基方面”的“虚切面”,类似C++中的类继承。
有了这个特性,就可以实现一些模式了,这里列出AOP中经典的观察者(Observer)模式[注]。
[注]这个说法不太妥当,观察者模式是经典的设计模式,这里的意思是说AOP经典的观察者模式实现。
它的代码如下:
其中“...” 部分是需要完成的C++实现代码,可以简单实现一个:
保存为ObserverPattern.ah供下面使用。
下面编写一个应用实例:
1、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++的匹配模式会不会混乱)
4、main.cc
这个程序编译运行,没有任何输出。有时候为了监视对象的状态,可以在执行一个操作后加上一些打印状态的代码,当然这样比较繁琐;也可以在各个操作函数中加入这些代码,但修改已经写好的代码总是不太舒服。
下面先实现一个Car状态打印类:
5、car_logging.h
6、car_logging.cc
7、CarLoggingObserver.ah
这个方面重写了subjects以及observers切面,并定义了observers在update被调用时执行的操作,另外还在Car的构造函数和析构函数中添加了注册和注销代码。
运行ac++生成代码,编译并运行,结果如下:
这里演示的例子依旧选择了不影响原始程序的做法,网上很多资料都把这个模式和实现代码结合起来,由于Aspect C++编译速度还是很慢,所以选择“外挂”的方式,这样不需要这些方面时,直接编译C++代码即可。
关于Aspect C++以及AOP,还有许多话题,不过不打算再继续了,AOP是个广泛的议题,局限在某一实现上只会使我们眼界变窄。
AOP被称为设计模式最佳实践者,它当之无愧。网上还有很多AOP实践设计模式的资料。
有了这个特性,就可以实现一些模式了,这里列出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 ) { }
};
// 管理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__
#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__
#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__
#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;
}
#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__
#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;
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__
#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实践设计模式的资料。
发表评论
-
Cilk++,XL
2009-08-05 10:04 2745刚看到CSDN新闻:Intel获得Cilk++技术 多核处理器 ... -
关于内存管理的一点想法
2009-07-14 16:11 1822分布式轻量级线程框架(还没取名)最近几个修改: 1、消息对象采 ... -
增加了monitor_node功能
2009-07-13 14:57 1867给分布式框架增加了类似 erlang 的 monitor_no ... -
轻量级线程切换效率
2009-07-13 12:07 2532同事测试了libcoro,它的linux版本可以使用4种模式, ... -
Cache Pool 架构
2009-06-16 10:05 3313先比较一下Hadoop。 Hadoop 架构: Cach ... -
高可用性Cache池
2009-06-15 16:10 4403前段时间开发上线了一个Cache池,使用双层Cache池冗余, ... -
抛开析构函数
2007-08-15 22:19 3444内存管理通常指的是堆 ... -
C++程序设计
2007-03-25 13:37 104上周在修改扩充同事的代码,发现几个问题。 1、访问级别几乎全 ... -
突发奇想续
2006-12-13 09:50 2020简单写了点代码,把那个方程组生成树结构: #include ... -
为C++实现一个IDL (零)
2005-09-15 01:27 4751一、问题。这段时间考虑实现一个纯C++的分布式服务包装库 ... -
为C++实现一个IDL (一)
2005-09-17 19:40 3033前面简单写了点静态结构,这一次将主要关注动态模型以及调用 ... -
正式建立asgard项目 (因ancients已经被人使用了)
2005-09-20 10:30 1938“为C++实现一个IDL” ... -
为C++实现一个IDL (二)
2005-09-20 22:34 2459说明:要看懂后面那部分代码,即使用Typelist的部分 ... -
为C++实现一个IDL (三)
2005-09-21 20:34 2761一、修正错误。首先修正第二篇中的一些错误,错误的内容可见 ... -
为C++实现一个IDL (四)
2005-09-22 19:13 2103如《为C++实现一个IDL(三)》一文中所说,还剩最后一 ... -
asgard项目遗留问题 (2005-09-27更新)
2005-09-24 17:00 1870asgard项目已经准备了 ... -
C++实现简单的类型库
2005-09-26 17:31 3038很久以前看到有人问“如何在C++中实现动态加载类”时,简 ... -
为C++实现一个IDL (五)
2005-09-28 22:57 2106本篇没什么清晰的目的,只是解释一下前面的几个问题,并提出 ... -
自己写的一个max函数
2005-12-12 10:45 1964CSDN上看到有人问能否实现一个效率较高的max函数,效 ... -
C++之AOP
2005-12-15 15:43 5798AOP是近年炒得很热,但却用得很少的一门技术,不过这并不 ...
相关推荐
C++中没有原生的AOP支持,但是可以通过一些编程技巧和设计模式来近似实现AOP。例如,可以通过继承和多态性来模拟切面的行为,或者利用函数指针、模板编程以及现代C++中的lambda表达式和函数对象来实现。此外,还有...
标题 "aop:aspect" 指涉的是Spring框架中的面向切面编程(Aspect-Oriented Programming, AOP)的一个核心概念。在Spring AOP中,`aop:aspect`是XML配置中定义一个切面的元素,它允许我们将关注点(如日志、事务管理...
知识点:面向切面编程(Aspect-Oriented Programming, AOP)与C++及Aspect C++ 在IT领域,尤其是软件工程和编程语言设计方面,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种重要的编程范式,旨在...
AOP 和 Aspect 注解切入 测试 Demo 1.ProxyFactory 基于 MethodBeforeAdvice、AfterReturningAdvice 利用 Spring Api 定义前、后置处理方法,并通过代理工厂类获取代理对象(代码或Xml配置实现) 2.ProxyFactoryBean...
在Java开发中,AOP(面向切面编程)是一种强大的编程范式,它允许程序员将关注点从核心业务逻辑中分离出来,如日志记录、事务管理、性能监控等。AOP通过“切面”这一概念,使得这些关注点可以模块化并独立于主要的...
整理的Spring AOP Aspect切入点语法,老师整理的,2018.08.01最新版
【标题】"aop实战.rar" 是一个关于面向切面编程(Aspect Oriented Programming, AOP)实践的压缩包,包含了一系列与AOP相关的文档和资料。AOP是一种编程范式,它允许开发者将关注点从核心业务逻辑中分离出来,如日志...
在没有专门支持AOP特性的C++环境中,可以通过一些特定的设计模式和技术来模拟AOP的功能。这些技术包括但不限于模板元编程、宏定义、函数指针、智能指针等。 ##### 3.2 限制 尽管纯C++可以通过各种手段实现一定程度...
1、@Aspect放在类头上,把这个类作为一个切面。 2、 @Pointcut放在方法头上,定义一个可被别的方法引用的切入点表达式。 3、5种通知。 3.1、@Before,前置通知,放在方法头上。 3.2、@After,后置【finally】...
在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从业务逻辑中分离出来,比如日志记录、事务管理、权限检查等。`@Aspect`是Spring AOP的核心注解,用于定义一个切面。下面我们将详细...
1. **Spring AOP**:AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架的一个重要特性,它允许开发者定义“切面”,这些切面可以包含业务逻辑的各个部分,如日志、事务管理等。Spring AOP提供了一种...
13. **观察者模式(Observer)**:Spring AOP并没有直接实现观察者模式,但在Spring事件模型中,`ApplicationEventPublisher`和`ApplicationListener`接口体现了观察者模式,允许对象注册监听并响应特定事件。...
也欢迎对AOP实战用法感兴趣的同学们加入。 使用场景及目标: 在生产环境中,通过巧妙的AOP机制,实现对日志的细致记录和处理。我们的目标是提高日志记录的效率和规范性,为监控和故障排查提供更为轻松便捷的工具。 ...
在Spring AOP中,我们通常使用@Aspect注解来定义切面类。切面类中可以包含多个通知(Advice),包括前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)和环绕通知...
Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的核心组件之一,它提供了一种在不修改源代码的情况下,对程序进行功能增强的技术。AOP允许开发者定义“切面”,这些切面可以封装跨越多个对象...
在XML配置中,我们创建一个`<aop:config>`元素,并定义`<aop:aspect>`子元素来声明切面: ```xml <aop:config> <aop:aspect id="loggingAspect" ref="loggingAspectBean"> <!-- ... --> </aop:aspect> </aop:...
### Spring之AOP介绍 #### 一、AOP概述 面向方面编程(Aspect-Oriented Programming,简称AOP)作为一种编程范式,旨在通过模块化的方式处理横切关注点(Cross-cutting Concerns)。传统的面向对象编程(OOP)虽然...
**AOP编程之AspectJ实战** 在软件开发中,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,旨在减少代码的重复性和提高模块化程度。AOP通过将关注点(如日志记录、事务管理、安全性检查等)...
Java 经典设计模式讲解以及项目实战 设计模式简介:主要介绍各种设计模式的概念和运用场景等 设计模式综合运用:主要是笔者在实际工作中运用到的一些设计模式综合运用事例的提炼 Spring设计模式简介:主要是讲述...