2014-11-26 4 views
0

Я хочу, чтобы избежать использования InstanceOf:Избегайте использования InstanceOf Patterns

вот мой случай:

Определение моих событий классы находятся в модуле в свободного городского:

public class Event1 extends AbstractEvent{ 

} 

public class Event2 extends AbstractEvent{ 

} 

public class Event3 extends AbstractEvent{ 

} 

в другом модуле под названием jms У меня есть слушатель, который принимает сообщение о событии из очереди:

public class MyMessageListener implements MessageListener { 

@Override 
public void onMessage(Message message) { 
// CONVERT message to Event Object 
    if (event instanceof Event1) { 
    // Execute Processing 1 
    } 

    if (event instanceof Event2) { 
    // Execute Processing 2 
    } 

    if (event instanceof Event3) { 
    // Execute Processing 3 
    } 

}

Я хочу, чтобы избежать использования instanceof и лучшие вещи делают это шаблон посетитель с execute методом в классах AbstractEvent и каждый лист будет осуществлять его.

Моя проблема заключается в том, что в общем пакете у меня нет доступа к классам, ответственным за обработку. классы тезисов существуют только в модуле jms.

Есть ли какие-либо советы или намек, чтобы сделать это (Advanced Visitor) или другой рисунок, чтобы сделать это

+0

Я бы добавил абстрактный метод к AbstractEvent и переместил код обработки на события – teodozjan

ответ

1

В таких случаях иногда могут помочь visitor Pattern. Шаблон посетителя в основном подходит, если иерархия классов не сильно меняется, потому что для каждого изменения иерархии классов вы также должны изменять посетителя (но это также так, если вы используете `instanceof ').

Чтобы использовать шаблон посетителя, вам нужно определить интерфейс Visitor, который содержит метод посещения для всех типов, которые вы хотите посетить:

interface Visitor { 
    visit(Event1 event); 
    visit(Event2 event); 
    visit(Event3 event); 
} 

первым вы хотите общий суперкласс, который является корнем для всех классов вы хотите применить посетителя. Этот суперкласс содержит метод callVisitor:

public abstract class MyEvent extends AbstractEvent { 
    public abstract void visit(Visitor v); 
} 

public class Event1 extends MyEvent{ 
    public void visit(Visitor v) { 
     v.visit(this); // calls visit(Event1) 
    } 
} 

public class Event2 extends MyEvent{ 
    public void visit(Visitor v) { 
     v.visit(this); // calls visit(Event2) 
    } 
} 

public class Event3 extends MyEvent{ 
    public void visit(Visitor v) { 
     v.visit(this); // calls visit(Event3) 
    } 
} 

Наконец, вы можете создать экземпляр посетителя каждый раз, когда вам нужно различное поведение в зависимости от типа исполнения класса:

public void onMessage(Message message) { 
    Visitor v = new Visitor() { 
     public void visit(Event1 event) { 
      // Execute Processing 1 
     } 
     public void visit(Event2 event) { 
      // Execute Processing 2 
     } 
     public void visit(Event3 event) { 
      // Execute Processing 3 
     } 
    } 
    event.visit(v); 
} 

Паттерн посетитель может быть избыточна в вашей ситуации, но иногда я считаю это полезным. Основным преимуществом использования instanceof и других возможных решений является то, что он является типичным: если вы добавите класс в иерархию, проект не будет компилироваться, пока вы не добавите метод посетителя ко всем посетителям, которые вы определили.

+0

Thansk для решения, отлично работать – Nabil

2

Сложите все возможные модели поведения для типа Map<Class, Runnable> и сочетать мероприятия и Runnable типа.

+0

Обратите внимание, что для этого необходимо, чтобы классы событий были окончательными или вы не признавали подклассы, которые не распознаются в качестве их родителя (или наоборот). – Darkhogg

+0

@ Darkhogg зависит от алгоритма соответствия. вы можете использовать 'instanceof', равноправие классов или что-то еще. –

0

Вы могли бы иметь AbstractEvent объявить абстрактную isOfType() метод:

public abstract class AbstractEvent { 
    public abstract boolean isOfType(String type); 
} 

Было бы устранить instanceof «S, но не переключение if, хотя ...

Приветствия,

1

As альтернативный подход к другим ответам, вы можете перенести логику принятия решения в конфигурацию сообщений, чтобы каждый тип события потреблялся MessageListener, предназначенным для обработки o один из видов Event. Это устранит любую логику «если» от вашего Потребителя.

Предостережение к этому подходу заключается в том, что несколько потребителей могут обрабатывать события не по порядку. Если это проблема для вашего проблемного домена, вы, возможно, не захотите самостоятельно решать проблемы вне очереди.

См JMS Selectors для получения дополнительной информации

Преимущества такого подхода являются:

  • Потребители несут ответственность только один тип событий (упрощение)
  • Вы можете добавить больше потребителей независимо в зависимости от типа события (масштабируемость)
Смежные вопросы