| 
View
 

Kata Message Handler - gruppo 2

Page history last edited by Ivan Gelpi 16 years, 10 months ago

Ivan Gelpi e Bruno Pasquali

 

Ciao ragazzi,

  scusate il ritardo ma ho avuto parecchio da fare nei giorni scorsi :-)

Ho dato proprio adesso un'occhiata a quanto fatto dal gruppo 3, di seguito vi posto la nostra soluzione... per alcuni aspetti è simile, per altri no (specie per la parte di Test, che non ho avuto modo ti completare, e che, devo ammettere, è un po' carente). Per il momento posto le classi con una descrizione sommaria, magari appena ho tempo metterò qualche commento più significativo! Nel caso interessasse, posso aggiungere uno zip con tutto il progettino nell'area Files.

Ciao a tutti

 

 

Main.java

Main che registra 3 Handler (gestore del messaggio), uno per ogni tipo di messaggio ammesso ("giallo", "verde" e "rosso"),

nell'HandlerRepository, che ha il compito di gestire la mappatura tra messaggio e l'implementazione dell'Handler relativo.

Quindi instanzia il MessageManager e richiama su di esso il metodo manageMessage() per ogni messaggio di esempio,

stampando il risultato prodotto dall'Handler sull'oggetto finale di esempio (object).


package main;

import handler.HandlerHelper;

import manager.MessageManager;

public class Main {

    public static void main(String[] args) {

       String msg1 = "Rosso";

       String msg2 = "Giallo";

       String msg3 = "Verde";

 

       HandlerHelper.registerHandler(msg1, "handler.RossoHandler");

       HandlerHelper.registerHandler(msg2, "handler.GialloHandler");

       HandlerHelper.registerHandler(msg3, "handler.VerdeHandler");

 

       TargetObject object = new TargetObject();

 

       MessageManager manager = new MessageManager();

 

       object.print(manager.manageMessage(msg1));

       object.print(manager.manageMessage(msg2));

       object.print(manager.manageMessage(msg3));

 

       System.out.println("OBJECT RESULT:\n" + object.read());

    }

}

 

TargetObject.java

Fa da wrapper al semplice oggetto target (uno StringWriter) su cui vengono eseguite le operazioni triggerate dai messaggi


package main;

import java.io.StringWriter;

public class TargetObject {

    private StringWriter writer = null;

    public TargetObject() {

        System.out.println("Instanziato TargetObject");

        writer = new StringWriter();

    }

    public void print(String input) {

        writer.write(input);

        writer.write("\n");

        writer.flush();

    }

    public String read() {

        return writer.toString();

    }

}

 

TestMessageFactory.java

JUnit test per testare l'avvenuta registrazione e recupero degli Handler tramite la Factory


package test;

import junit.framework.TestCase;

import handler.MessageHandlerFactory;

import handler.MessageHandler;

import handler.RossoHandler;

import handler.HandlerHelper;

public class TestMessageFactory extends TestCase {

    public void setUp() throws Exception  {

        HandlerHelper.registerHandler("Rosso", "handler.RossoHandler");

        HandlerHelper.registerHandler("Giallo", "handler.GialloHandler");

        HandlerHelper.registerHandler("Verde", "handler.VerdeHandler");

    }

    public void testRegisterHandler() throws Exception {

        assertEquals("size mappa errato", 3, HandlerHelper.getHandlerMapSize());

    }

    public void testGetHandler() throws Exception {

        String msg1 = "Rosso";

        MessageHandler handler = MessageHandlerFactory.getHandler(msg1);

        assertNotNull("oggetto non istanziato", handler);

 

        assertEquals("tipo di oggetto errato", RossoHandler.class, handler.getClass());

    }

}

 

MessageManager.java

Classe che ha il compito di instanziare l'handler corretto (grazie alla Factory) e di eseguirvi il metodo processMessage()


package manager;

import handler.MessageHandlerFactory;

import handler.MessageHandler;

public class MessageManager {

    public String manageMessage(String message)  {

        MessageHandler handler = MessageHandlerFactory.getHandler(message);

        return handler.processMessage();

    }

 

}

 

MessageHandlerFactory.java

Factory che ha il compito di instanziare l'opportuno oggetto MessageHandler, in base al messaggio ricevuto


package handler;

public class MessageHandlerFactory {

    public static MessageHandler getHandler(String message) {

        MessageHandler handler = null;

        String handlerClass = HandlerRepository.getInstance().getHandler(message);

        try {

            handler = (MessageHandler) Class.forName(handlerClass).newInstance();

        } catch (Exception e) {

            System.out.println("Errore nella creazione dell'handler: " + handlerClass);

            e.printStackTrace();

        }

        return handler;

    }

}

 

HandlerRepository.java

Singleton che ha lo scopo di mantenere le classi degli Handler tramite una mappa <String message, String HandlerClass>


package handler;

import java.util.HashMap;

import java.util.Map;

public class HandlerRepository {

    private static final HandlerRepository instance = new HandlerRepository();

    //Handlers map

    private Map<String, String> handlerMap = new HashMap<String, String>();

    private HandlerRepository() {}

    public static HandlerRepository getInstance() {

        return instance;

    }

    public void addHandler(String message, String handler) {

        handlerMap.put(message, handler);

    }

    public String getHandler(String message) {

        return handlerMap.get(message);

    }

    public int getHandlerMapSize() {

        return handlerMap.size();

    }

}

 

HandlerHelper.java

Pura classe Helper, creata solo per facilitare la registrazione degli Handler nell'HandlerRepository


package handler;

public class HandlerHelper {

    public static void registerHandler(String message, String handler) {

        HandlerRepository.getInstance().addHandler(message, handler);

    }

    public static int getHandlerMapSize() {

        return HandlerRepository.getInstance().getHandlerMapSize();

    }

}

 

MessageHandler.java

Interfaccia per gli oggetti Handler; per ora prevede il solo metodo processMessage();


 

package handler;

public interface MessageHandler {

    public String processMessage();

}

 

GialloHandler.java

RossoHandler.java

VerdeHandler.java

Implementazioni degli Handler, uno per tipologia di messaggio; implementano il metodo processMessage() dell'interfaccia MessageHandler


 

package handler;

public class GialloHandler implements MessageHandler {

    public String processMessage() {

        return "Processed Giallo Message";

    }

}

 

package handler;

public class RossoHandler implements MessageHandler {

    public String processMessage() {

        return "Processed Rosso Message";

    }

}

 

package handler;

public class VerdeHandler implements MessageHandler {

    public String processMessage() {

        return "Processed Verde Message";

    }

}

 

NOTE SULL'ESECUZIONE


Il test passa ;-) e il Main produce il seguente output:

 

Instanziato TargetObject

OBJECT RESULT:

Processed Rosso Message

Processed Giallo Message

Processed Verde Message

 

 

 

 

 

Comments (2)

Ivan Gelpi said

at 10:04 am on Nov 12, 2009

Una possibile miglioria, che è alla base di molte tecnologie ed è applicabile nel nostro caso in cui abbiamo un handler per ogni messaggio,
è quella di istanziare l'handler corrispondete al messaggio direttamente in base al nome del messaggio (tenendo fisso il package dove andiamo a creare gli handler, ad esempio handler.*, la classe handler di un dato messaggio sarà facilmente ricavabile sostituendo la stringa del messaggio all rispettivo base name della classe; in altre parole, rosso diventerà handler.RossoHandler, giallo handler.GialloHanderl e così via).

Quindi, con l'unica accortezza che l'inziale del messaggio sia uppercase, e il resto in lowercase, dato il nome di un messaggio, il codice della factory diventa (risparmio il codice per modificare il messaggio nel corretto case, supponendo quindi che arrivi già corretto alla Factory:

package handler;

public class MessageHandlerFactory {

public static MessageHandler getHandler(String message) {

MessageHandler handler = null;

String handlerClass = "handler." + message + "Handler";

try {

handler = (MessageHandler) Class.forName(handlerClass).newInstance();

} catch (Exception e) {

System.out.println("Errore nella creazione dell'handler: " + handlerClass);

e.printStackTrace();

}

return handler;

}

}

Ivan Gelpi said

at 10:04 am on Nov 12, 2009

In questo modo quindi possiamo fare completamente a meno della mappa e quindi della gestione dell'HandlerRepository, basta solamente fare attenzione a creare le classi degli handler con il nome corretto (ma quello già lo dobbiamo fare).

Personalmente ho preferito gestire comunque la mappa degli handler per maggiore configurabilità, e per rendere la cosa un filo più interessante: con la mappa ad esempio si possono gestire più messaggi tramite lo stesso handler, quindi seppur più complicata e meno efficiente, la prima soluzione è maggiormente adattabile a un cambio di esigenze o a modifiche ai requisiti, altro punto importante che avevamo preso in considerazione oltre all'eliminazione degli if.

Un saluto a tutti.

You don't have permission to comment on this page.