DCI框架中的语法糖:
-
DEFINE_ROLE
:用于定义role。DEFINE_ROLE
的本质是创建一个包含了虚析构函数的抽象类,但是在DCI框架里面使用这个命名更具有语义。DEFINE_ROLE
定义的类中需要至少包含一个虚方法或者使用了USE_ROLE
声明依赖另外一个role。 -
USE_ROLE
:在一个类里面声明自己的实现依赖另外一个role。 -
ROLE
:当一个类声明中使用了USE_ROLE
声明依赖另外一个类XXX后,则在类的实现代码里面就可以调用ROLE(XXX)
来引用这个类去调用它的成员方法。
交织方式语法糖:
- IMPL_ROLE:在多重继承树内进行关系交织来进行role之间的依赖关系描述。
IMPL_ROLE_WITH_OBJ
: 当持有被依赖role的一个引用或者成员的时候,使用IMPL_ROLE_WITH_OBJ
进行关系交织。DECL_ROLE
: 自定义交织关系。
方式一:
DEFINE_ROLE
:该语法糖和HAS_ROLE一起使用来实现物理依赖隔离。
HAS_ROLE
: 用于在一个纯接口类中声明领域对象可被context访问的所有public role,该纯接口类是领域对象的一个抽象层。该语法糖和
DEFINE_ROLE
一起使用来实现物理依赖隔离,例子如下:
DEFINE_ROLE(Human)
{
HAS_ROLE(Worker);
};
struct HumanObject : Human
, private Worker
, private HumanEnergy
{
private:
IMPL_ROLE(Worker);
IMPL_ROLE(Energy);
};
struct HumanFactory
{
static Human* create()
{
return new HumanObject;
}
};
TEST(...)
{
Human* human = HumanFactory::create();
human->ROLE(Worker).produce();
ASSERT_EQ(1, human->ROLE(Worker).getProduceNum());
delete human;
}
方式二:
- DEF_INTERFACE:用于定义一个接口role,该语法糖和HAS_ROLE一起使用来实现物理依赖隔离。
-
HAS_ROLE
:该语法糖和DEF_INTERFACE一起使用来实现物理依赖隔离,例子如下:
DEF_INTERFACE(Worker, 0x12341234)
{
HAS_ROLE(Worker);
};
struct HumanObject : dci::Unknown
, Worker
, private HumanEnergy
{
BEGIN_INTERFACE_TABLE()
__HAS_INTERFACE(Worker)
END_INTERFACE_TABLE()
private:
IMPL_ROLE(Energy);
};
struct HumanFactory
{
static dci::Unknown* create()
{
return new HumanObject;
}
};
TEST(...)
{
dci::Unknown* unknown = HumanFactory::create();
Worker* worker = dci::unknown_cast<Worker>(unknown);
ASSERT_TRUE(__notnull__(worker));
worker->produce();
ASSERT_EQ(1, worker->getProduceNum());
delete unknown;
}
其中,DCI框架中提供了一个公共的接口类dci::Unknown
,该接口需要被领域对象public继承。能够从dci::Unknown
被转化到的目标role需要用DEF_INTERFACE
来定义,参数是类名以及一个32位的随机数。这个随机数需要程序员自行提供,保证全局不重复(可以写一个脚本自动产生不重复的随机数,同样可以用脚本自动校验代码中已有的是否存在重复,可以把校验脚本作为版本编译检查的一部分)。领域对象类继承的所有由DEF_INTERFACE
定义的role都需要在BEGIN_INTERFACE_TABLE()
和END_INTERFACE_TABLE()
中由__HAS_INTERFACE
显示注册一下(参考上面代码中HumanObject
的写法)。最后,context持有领域对象工厂返回的dci::Unknown
指针,通过dci::unknown_cast
将其转化目标role使用,至此这种机制和dynamic_cast
的用法基本一致,在无法完成转化的情况下会返回空指针,所以安全起见需要对返回的指针进行校验。
DCI框架中的宏:
#define ABSTRACT(...) virtual __VA_ARGS__ = 0
#define OVERRIDE(...) virtual __VA_ARGS__ override