вторник, 3 марта 2009 г.

Notificator

При работе с контейнерами (особенно древовидными) часто необходимо организовывать рассылку сообщений по факту изменений происходящих в контейнере.
Для решения этой задачи я использовал простое решение - класс-уведомитель CollectionNotificators.
Поддерживаются три типа события:
  • Add - добавлен элемент в контейнер
  • Remove - удалён элемент из контейнера
  • Change - изменен элемент контейнера

Реализуемый интерфейс приведён ниже.
/*******************************************************************************
* Copyright (c) 2009 Evgeny P. Florov.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU GENERAL PUBLIC LICENSE Version 3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*******************************************************************************/
package org.inno.des.utils;

/***
* Interface for all collections (container of items) event notificators
* @author Evgeny P. Florov
*
*/


public interface ICollectionNotificators {
/***
* Interface for events, that applicate for items. Abstract parent for all other events
* @author Ecgeny P. Florov
*/
public interface IEvents{
public Object getSubject();
}

/***
* Interface for events, that started by container changes - for example - remove chield from trees node
* @author Evgeny P. Florov
*/
public interface IContainerEvents extends IEvents{
public Object getContainer();
}

/***
* Interface for events, that applicated for item changes, for example - change some property of item
* @author Evgeny P. Florov
*/
public interface ISubjectChangeEvents extends IEvents{
public String getId();
}

/***
* Supported listener of events
* @author Evgeny P. Florov
*/
public interface IListeners{
/***
* Called after "add" event occur.
* @param event - descript add event
*/
public void onAdd(IContainerEvents event);
/***
* Called after "remove" event occure
* @param event - descript remove event
*/
public void onRemove(IContainerEvents event);
/***
* Called after "change" event occure
* @param event - descript change event
*/
public void onChange(ISubjectChangeEvents event);
}

/***
* Add listener to this notificator
* @param subj - listener to add
*/
public void add(IListeners subj);

/***
* Remove listener from this notificator
* @param subj - listener to remove
*/
public void remove(IListeners subj);

/***
* Interface for object, that started events. Only service function - not requared
* @author Evgeny P. Florov
*
*/
public interface IEventFirestarters{
public void fireAddEvent(Object subject, Object container);
public void fireRemoveEvent(Object subject, Object container);
public void fireChangeEvent(Object subject, String id);
}
}


Пример использования довольно прост. Достаточно инстанцировать нотификатор (например как аттрибут контейнера) и по мере необходимости инициировать события вызовом fire***Event.
Естественно для получения событий клиенты должны реализовать ICollectionNotificators.IListeners и зарегистрироваться в объекте нотификатора.

Ниже приведён облегченный код JUnit теста:


/*******************************************************************************
* Copyright (c) 2009 Evgeny P. Florov.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU GENERAL PUBLIC LICENSE Version 3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*******************************************************************************/
package org.inno.des.utils.tests;

import java.util.ArrayList;

import org.inno.des.utils.CollectionNotificators;
import org.inno.des.utils.ICollectionNotificators;
import org.inno.des.utils.ICollectionNotificators.IContainerEvents;
import org.inno.des.utils.ICollectionNotificators.ISubjectChangeEvents;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
* Test unit for CollectionNotificators
* @author Evgeny P. Florov
*
*/
public class CollectionNotificatorsTest {

private class ExDublicateFound extends RuntimeException{
}

private final int MAX_LISTENERS = 1000;

private ArrayList listeners = new ArrayList();

private CollectionNotificators test;

public int addcount = 0;
public int changecount = 0;
public int removecount = 0;

private class Listener implements ICollectionNotificators.IListeners{

private int number = 0;

public Listener(int number){
this.number = number;
}

@Override
public void onAdd(IContainerEvents event) {
addcount++;
}

@Override
public void onChange(ISubjectChangeEvents event) {
changecount++;
}

@Override
public void onRemove(IContainerEvents event) {
removecount++;
}
}


public CollectionNotificatorsTest() {
for(int i = 0; i < addcount =" 0;" changecount =" 0;" removecount =" 0;" test =" new" stealthmode =" true;" i =" 0;">

Комментариев нет: