假设我有一个这样的类:
class User{
String name;
String email;
int age;
Role[] role;
// other fields.
// constructors, getters , setters , ...
}
字符串
其中“Role”是另一个定义的类(或枚举,无所谓)。
现在假设我有一个名字列表,一个年龄列表,一个角色列表(或者一个角色数组列表),...(其他可能的字段),我想创建这些字段的所有可能组合来创建所有用户组合(字段的笛卡尔乘积)。
List<User> factory(Map<String , List> arguments){
List<User> result = new ArrayList<>();
// add all possible combination of created Users using "arguments" paramether.
return result;
}
型
问题是提供的参数的数量是不确定的,例如,在我的应用程序的一部分,我不想提供电子邮件列表,所以所有创建的用户都有“空”电子邮件字段。
我怎样才能有效地获得适当的结果?(有图书馆之类的吗?)如果有必要,可以随意更改“工厂”方法的输入参数或输出。
P.s:我们正在开发一个Sping Boot Web应用程序,我们用Junit和Mockito测试了我们的方法。我们想要用大量的数据测试不同层的方法,但是我们不想用重复的代码来生成样本。我们需要一个类似于“工厂”的方法来生成一个类的所有可能的对象。
1条答案
按热度按时间h22fl7wq1#
一般来说,形成你所描述的那种笛卡尔积的正常方法是使用一组嵌套循环或类似的浅递归。
问题是提供的参数的数量是不确定的,例如,在我的应用程序的一部分,我不想提供电子邮件列表,所以所有创建的用户都有“空”电子邮件字段。
我怎样才能有效地获得适当的结果?(有图书馆之类的吗?)如果有必要,可以随意更改“工厂”方法的输入参数或输出。
您的选择多少取决于
User
的细节。例如,它有什么构造函数,或者你愿意给予它什么构造函数?示例初始化后,其(所有)字段是否可修改?一种灵活的方法,适用于几乎任何细节,将涉及一个有状态的工厂类,类似于这样:
字符串
这样的工厂可以帮助您以灵活的方式为
User
构建一组属性,并抽象出实际创建具有所需属性的User
示例的细节。但是,如果您打算通过Map或类似的方式指定属性值列表,那么您需要一种方法来使用该Map的键来设置工厂(或
User
)属性。对于我们的目的,将其放在工厂类中是很方便的,并且这还有保持User
更干净的额外好处:型
有各种各样的方法可以实现它,但重要的是要认识到,使用该签名,它必须依赖于值对象的类型转换。有一些方法可以从这样的东西中提取类型安全,但是它们会增加更多的复杂性,而对于测试支持实用程序来说,这已经非常复杂了。我觉得不值得。
有了这些,工厂类也是一个合理的地方,可以挂起一个生成你想要的
User
列表的方法,可能是这样的:型
它使用递归(每个属性名一个级别)并结合属性值列表上的迭代,最终为每个属性值组合生成一个
User
。如果在传递给顶层调用的Map中没有列出任何属性,则在结果User
s上设置的这些属性的值将由提供的UserFactory
示例确定。但请注意:
User
。可能很多人都是。如果你想避免这种可能性,那么你可以考虑修改它,使用Set
s而不是List
s作为属性,但这只对某些类型的属性值有帮助(特别是,not 用于数组)。Role
s或类似的),则需要复制这些值,可能在UserFactory.createUser()
中,否则接受User
对象将具有共享的可变状态。后者很容易给你带来不愉快的惊喜。