利用零碎时间,断断续续自学了一个月Rust,实现了DDD中实体在Rust中的设计规范,就这么个小东西,也遇到了无数的坑,被编译器无数次无情地打脸,Rust的生命周期确实是一个需要好好研究的东西,大部分错误都是基于此
说是实体的设计规范,实际上也包含了诸如包模块的建立与使用、静态变量的使用、闭包的封装、继承的实现等功能,可以当作一个Rust的入门Demo吧
目前项目里有一个fwlibrary的库包,一个fwtest的可执行包,fwtest调用fwlibrary,fwlibrary中有modelbase结构体,作为DDD实体的基类,帮助实体存储使用属性,entitya为demo使用的实体类,包含几个属性以及一个方法,继承自modelbase
以下是几个要点,说明一下
1,rust没有严格意义上的继承,是使用包含的方式来曲线实现的,所幸rust标准包中有Deref、DerefMut,可以帮我们实现行为的继承
2,实体采用结构体来实现,目前网上看到的很多实体都是直接使用结构体字段来作为实体属性使用,这个是不对的,会有很大的问题,涉及到所有权的问题,会破坏OO的数据完整性原则,因此,所有属性采用getxxx、setxxx方法的方式来公开,类似于java,
所有实体实例数据由ModelBase维护,所有权归属实体实例所有,对于非基础类型,getxxx只获取借用,不会将内部数据控制权外泄
3,实体行为采用桥接模式实现,在系统初始化的时候,可以替换实际实现
4,实体结构体提供new方法,充当构造函数
5,采用静态变量才维护桥接工厂,以后凡是有静态数据存储,都使用此方式,需要考虑并发
6,其他诸如泛型、包管理、闭包等等,不多说了,直接看代码即可
在main中,实现了另外一个实体行为的实现,通过取消开头的注释,即可在初始化时替换掉默认行为实现
以下是主要代码,这里居然没有rust的代码模板,靠
modelbase.rs
use std::collections::HashMap; use std::any::Any; use std::default; use std::mem; pub struct ModelBase<'a>{ datas:HashMap<&'a str,Box<dyn Any>> } impl<'a> ModelBase<'a>{ pub fn new()->ModelBase<'a>{ ModelBase{ datas:HashMap::new() } } pub fn getattribute<T: 'static>(&self,attname:&'a str)->Option<&T> { if let Some(v) = self.datas.get(&attname){ if let Some(x) =(*v).downcast_ref::<T>() { return Some(x); } else { let v:Option<&T>=None; return v; } } else{ let v:Option<&T>=None; return v; } } pub fn setattribute<T: 'static>(&mut self,attname:&'a str,value:T) { self.datas.insert(attname, Box::new(value)); } }
entitya.rs
use std::ops::Deref; use std::ops::DerefMut; use std::sync::Arc; use std::sync::Once; use crate::modelbase::*; static INIT: Once = Once::new(); pub static mut ENTITYAIMPSTATICFACTORY:Option<Arc<dyn Fn()->Box<dyn EntityAIMP>+Send+Sync>>=None; pub struct EntityA<'a>{ base:ModelBase<'a>, imp:Box<dyn EntityAIMP> } impl Deref for EntityA<'static>{ type Target=ModelBase<'static>; fn deref<'a>(&'a self)->&'a ModelBase<'static>{ &self.base } } impl DerefMut for EntityA<'static>{ fn deref_mut<'a>(&'a mut self)->&'a mut ModelBase<'static>{ &mut self.base } } pub trait EntityAIMP { fn test(&self, entity:&EntityA)->&str; } impl<'a> EntityA<'a>{ pub fn new()->EntityA<'a>{ let realimp:Box<dyn EntityAIMP>; unsafe { INIT.call_once(|| { if let None = ENTITYAIMPSTATICFACTORY{ let x:Arc<dyn Fn()->Box<dyn EntityAIMP>+Send+Sync>=Arc::new(||->Box<dyn EntityAIMP> { Box::new(EntityARealIMP::new()) }); ENTITYAIMPSTATICFACTORY = Some(x); } }); if let Some(v) = &ENTITYAIMPSTATICFACTORY{ realimp=v(); } else { realimp=Box::new(EntityARealIMP::new()); } } EntityA{ base:ModelBase::new(), imp:realimp } } pub fn getid(&self)->&str{ let value=self.base.getattribute::<String>("id"); let mut result:&str =Default::default(); if let Some(v) = value { result=v; } result } pub fn setid(&mut self,value:String){ self.base.setattribute::<String>("id",value); } pub fn getremark(&self)->Option<&str>{ let value=self.base.getattribute::<Option<String>>("remark"); let mut result:Option<&str> = Option::None; if let Some(v) = value { if let Some(iv)=v{ result=Option::Some(iv); } } result } pub fn setremark(&mut self,value:Option<String>){ self.base.setattribute::<Option<String>>("remark",value); } pub fn test(&self)->&str{ self.imp.test(self) } } pub struct EntityARealIMP(); impl EntityARealIMP{ pub fn new()->EntityARealIMP { EntityARealIMP{} } } impl EntityAIMP for EntityARealIMP { fn test(&self,entity:&EntityA)->&str{ "eeee" } }
main.rs
extern crate lazy_static; extern crate fwlibrary; use std::ops::Deref; use std::ops::DerefMut; use std::sync::Arc; /*struct A{ name:String } struct B { a:A, role:String } struct C { b:B, age:i32 } impl A{ fn new()->A { A { name:"w".to_string() } } fn a1(&self)->&str { &*self.name } } impl C{ fn new()->C{ C{ b:B::new(), age:12 } } fn c1(&self)->i32{ self.age } } impl B{ fn new()->B{ B{ a:A::new(), role:"r".to_string() } } fn b1(&self)->&str { &*self.role } } impl Deref for B{ type Target=A; fn deref<'a>(&'a self)->&'a A{ &self.a } } impl DerefMut for B{ fn deref_mut<'a>(&'a mut self)->&'a mut A{ &mut self.a } } impl Deref for C{ type Target=B; fn deref<'a>(&'a self)->&'a B{ &self.b } } impl DerefMut for C{ fn deref_mut<'a>(&'a mut self)->&'a mut B{ &mut self.b } } fn a1(c:&C) { } fn a2(c:C)->C { c } fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str { if s2.len() > s1.len() { s2 } else { s1 } } struct V(); fn vtest(v:& mut V) { } */ struct EntityAReal1IMP(); impl EntityAReal1IMP{ fn new()->EntityAReal1IMP { EntityAReal1IMP{} } } impl fwlibrary::EntityAIMP for EntityAReal1IMP { fn test(&self,entity:&fwlibrary::EntityA)->&str{ "fffff" } } fn main() { unsafe{ let x:Arc<dyn Fn()->Box<dyn fwlibrary::EntityAIMP>+Send+Sync>=Arc::new(||->Box<dyn fwlibrary::EntityAIMP> { Box::new(EntityAReal1IMP::new()) }); fwlibrary::ENTITYAIMPSTATICFACTORY = Some(x); } let mut entitya=fwlibrary::EntityA::new(); let rentitya=&entitya; let ma=entitya.test(); entitya.setid(String::from("11")); entitya.setremark(Some(String::from("xxxx"))); let aid=entitya.getid(); entitya.setremark(Option::Some(String::from("cccc"))); let aremark=entitya.getremark(); let remark= aremark.unwrap(); /*let mut ii: V=V{}; let iia=&mut ii; vtest(iia); let ii1=ii; let mut e1=1; let mut e2=&e1; let mut e3=e2+4; let mut model=fwlibrary::ModelBase::new(); model.setattribute::<String>("aa",String::from("11")); let modelV=model.getattribute::<String>("aa"); let v=modelV.unwrap(); let c=C::new(); let l=&c; //a2(c); //let str1=c.a1(); println!("{}","");*/ }
github源码地址https://github.com/rhw1111/Rust