Java 过滤未知类型对象的最干净模式?
我有一个应用程序,它从队列中获取json对象,将它们反序列化到模型,应用过滤器列表,并将通过所有过滤器的对象发送到另一个队列 两个复杂的标准是:Java 过滤未知类型对象的最干净模式?,java,spring,design-patterns,Java,Spring,Design Patterns,我有一个应用程序,它从队列中获取json对象,将它们反序列化到模型,应用过滤器列表,并将通过所有过滤器的对象发送到另一个队列 两个复杂的标准是: 过滤器组在启动时通过弹簧剖面确定和注入 json反序列化到的对象类型也由启动时的Spring概要文件确定 以下解决方案很难看,因为它涉及铸造: public class MessageTypeOne { public int someField; } public class MessageTypeTwo { public int
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter {
boolean doesFilterPass(Object object);
}
@Component
@Profile("ProfileOne")
public class OneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeOne message = (MessageTypeOne)object;
if (message.someField == something) {
return false;
} else return true;
}
}
@Component
@Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
}
@Service
public class MessageFilterService {
// injected at runtime via Spring profile
private Set<MessageFilter> messageFilters
@AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(Object object) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(object)) {
return false;
}
}
return true;
}
}
公共类MessageTypeOne{
公共领域;
}
公共类消息类型2{
公共领域;
}
公共接口消息过滤器{
布尔doesFilterPass(对象);
}
@组成部分
@简介(“简介一”)
公共类OneOfMyMessageFilters实现MessageFilter{
公共布尔doesFilterPass(对象){
MessageTypeOne消息=(MessageTypeOne)对象;
if(message.someField==something){
返回false;
}否则返回true;
}
}
@组成部分
@简介(“简介二”)
另一个公共类MyMessageFilters实现MessageFilter{
公共布尔doesFilterPass(对象){
MessageTypeTwo message=(MessageTypeTwo)对象;
if(message.otherField==something){
返回false;
}否则返回true;
}
}
@服务
公共类MessageFilterService{
//通过Spring配置文件在运行时注入
私有集消息过滤器
@自动连线
公共消息过滤器服务(设置消息过滤器){
this.messageFilters=messageFilters;
}
公共布尔passesAllFilters(对象对象)引发IOException{
用于(MessageFilter筛选器:messageFilters){
如果(!filter.doesFilterPass(对象)){
返回false;
}
}
返回true;
}
}
这种箱子最干净的式样是什么?我读过关于访问者模式的文章,但我不确定这是否比这样的角色扮演更好。就设计模式而言,我认为这是一种策略模式。我不是在谈论Spring的实现方式。您可能有n个筛选器,但必须根据上下文进行选择。所以战略模式最适合这里。其他人可以提供其他模式。您可以在下面的链接中选择策略模式
使用Java反射的访问者模式如何?这是一篇老文章:
当您想要将消息与筛选器分离,并且关系是多对多的时,您可以随时使用 抽象类包含链逻辑,您只需要在每个子类中实现两个方法。其中一个实现可能如下所示:
public abstract class MessageFilter {
private MessageFilter next;
//constructors, setters, etc
public boolean doesFilterPass(Object object) {
boolean res = true;
if (canHandle(object)) {
res = validate(object);
}
return res && next.doesFilterPass(object);
}
public abstract boolean validate(Object object);
public abstract boolean canHandle(Object object);
}
public class AnotherOneOfMyMessageFilters extends MessageFilter {
public boolean canHandle(Object object) {
return object instanceof MessageTypeTwo;
}
public boolean validate(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
return message.otherField == something;
}
}
上面所有的类都只是在没有IDE的情况下创建的示例,所以可能在语法上有问题,但应该让您了解它应该如何工作
另见:
ClassCastException
s
假设您的配置选项是您想要的方式,那么它说明了您的设计中唯一真正的问题——您的过滤器可以应用于任何对象
,这就是界面所说的——doesFilterPass(对象)——但您的过滤器只适用于特定类型的对象
这就是你需要解决的问题。如果过滤器应用于奇怪类型的对象,它是通过还是失败?您可以根据每个过滤器来决定,然后按如下方式进行修复:
public boolean doesFilterPass(Object object) {
if (!(object instanceOf MessageTypeTwo)) {
return true;
}
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
简单的豌豆
我知道您不喜欢强制转换,但这是您提供的配置选项的直接结果--配置文件可以配置为对任何类型的对象应用过滤器。您只需要支持它,这意味着必须在某个地方进行强制转换。这在泛型中变得更加清晰。因为我知道每个过滤器可以处理什么类型的对象,所以我可以这样做,消除强制转换:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter<T> {
boolean doesFilterPass(T message);
}
@Component
@Profile("ProfileOne")
public class OneOfMyMessageFilters<T extends MessageTypeOne> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeOne message) {
if (message.someField == something) {
return false;
} else return true;
}
}
@Component
@Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters<T extends MessageTypeTwo> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeTwo message) {
if (message.otherField == something) {
return false;
} else return true;
}
}
@Service
public class MessageFilterServiceImpl<T> implements MessageFilterService<T> {
// injected at runtime via Spring profile
private Set<MessageFilter<T>> messageFilters
@AutoWired
public MessageFilterService(Set<MessageFilter<T>> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(T message) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(message)) {
return false;
}
}
return true;
}
}
public interface MessageFilterService<T> {
boolean passesAllFilters(T rawEvent) throws IllegalArgumentException;
}
公共类MessageTypeOne{
公共领域;
}
公共类消息类型2{
公共领域;
}
公共接口消息过滤器{
布尔doesFilterPass(T消息);
}
@组成部分
@简介(“简介一”)
公共类OneOfMyMessageFilters实现MessageFilter{
公共布尔doesFilterPass(MessageTypeOne消息){
if(message.someField==something){
返回false;
}否则返回true;
}
}
@组成部分
@简介(“简介二”)
另一个公共类MyMessageFilters实现MessageFilter{
公共布尔值doesFilterPass(MessageTypeTwo消息){
if(message.otherField==something){
返回false;
}否则返回true;
}
}
@服务
公共类MessageFilterServiceImpl实现MessageFilterService{
//通过Spring配置文件在运行时注入
私有集消息过滤器
@自动连线
公共消息过滤器服务(设置消息过滤器){
this.messageFilters=messageFilters;
}
公共布尔passesAllFilters(T消息)引发IOException{
用于(MessageFilter筛选器:messageFilters){
如果(!filter.doesFilterPass(消息)){
返回false;
}
}
返回true;
}
}
公共接口MessageFilterService{
布尔passesAllFilters(T rawEvent)抛出IllegalArgumentException;
}
我可以给你两个建议。关于过滤,您可以使用责任链模式。关于消息类型,您可以使用MessageTypeOne和MessageTypeTwo实现的接口MessageType,然后将接口作为参数传递以隐藏实现(称为策略模式)。这不起作用。过滤器将需要使用特定消息类型实现的字段来决定是否对其进行过滤。我不知道这对我的案例如何起作用,因为策略模式涉及对参数执行不同的操作
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter<T> {
boolean doesFilterPass(T message);
}
@Component
@Profile("ProfileOne")
public class OneOfMyMessageFilters<T extends MessageTypeOne> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeOne message) {
if (message.someField == something) {
return false;
} else return true;
}
}
@Component
@Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters<T extends MessageTypeTwo> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeTwo message) {
if (message.otherField == something) {
return false;
} else return true;
}
}
@Service
public class MessageFilterServiceImpl<T> implements MessageFilterService<T> {
// injected at runtime via Spring profile
private Set<MessageFilter<T>> messageFilters
@AutoWired
public MessageFilterService(Set<MessageFilter<T>> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(T message) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(message)) {
return false;
}
}
return true;
}
}
public interface MessageFilterService<T> {
boolean passesAllFilters(T rawEvent) throws IllegalArgumentException;
}