DCI in C++ 语法糖

本文介绍了DCI框架中的关键概念,包括DEFINE_ROLE、USE_ROLE、ROLE等语法糖,并详细解释了如何利用这些特性实现角色间的依赖关系及物理依赖隔离。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

DCI(Data, Context, Interaction)架构是一种软件设计模式,旨在将对象的行为与其数据分离,从而提高代码的可读性和可维护性。它强调“角色”这一概念——即在特定场景下某个对象所扮演的角色及其对应的行为。 ### C++ 实现 DCI 架构 #### 数据部分 (Data) 这是指系统中的核心实体类。这些类通常只包含属性和基本操作,并不涉及复杂的业务逻辑。例如,在一个简单的银行应用中,“账户”可以作为一个基础的数据类: ```cpp class Account { public: double balance; Account(double initialBalance) : balance(initialBalance) {} void deposit(double amount) { balance += amount; } }; ``` #### 角色部分 (Role) 每个数据实例可以根据当前的情境扮演某些角色。比如转账时两个账户分别充当转出方和转入方。我们可以为每种角色创建接口并由实际的对象动态地承担该职责。 ```cpp struct TransferSource { virtual bool hasEnoughMoney(double amount) = 0; virtual void withdraw(double amount) = 0; }; struct TransferTarget { virtual void deposit(double amount) = 0; }; ``` 然后让具体的Account去实现上述抽象角色的功能: ```cpp class DebitableAccount : public Account, public TransferSource { public: using Account::Account; bool hasEnoughMoney(double amount) override { return this->balance >= amount; } void withdraw(double amount) override { if(hasEnoughMoney(amount)) { this->balance -= amount; } else { throw std::runtime_error("Insufficient funds"); } } }; // 同理定义CreditableAccount... ``` #### 上下文管理(Context & Interaction) 最后一步就是设置好交互环境了。我们需要编写一段专门负责协调各个参与者之间关系以及触发动作序列的程序段落: ```cpp class MoneyTransferContext { private: TransferSource& source_; TransferTarget& target_; public: MoneyTransferContext(TransferSource& src, TransferTarget& tgt):source_(src),target_(tgt){} void execute(double amount){ if(source_.hasEnoughMoney(amount)){ source_.withdraw(amount); target_.deposit(amount); }else{ // Handle insufficient funds error. } } }; ``` 通过这种方式我们就能清晰地区分出系统的静态结构和运行时刻的变化情况啦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值