7b_IFT232_DesignPatterns_FactoryMethod

publicité
Schéma de conception
Factory Method
Exemple
Sylvain Giroux
Problème
 Tout programme doit pouvoir rapporter les erreurs ou
encore afficher des messages servant pour le déverminage.
public interface Trace {
// turn on and off debugging
public void setDebug( boolean debug );
// write out a debug message
public void debug( String message );
// write out an error message
public void error( String message );
}
Première version
 Écrire une classe SystemTrace qui
implémente Trace.
 Les instances de cette classe affiche le
résultat dans la fenêtre de commande en
ligne.
La classe SystemTrace
public class SystemTrace implements Trace {
private boolean debug;
public void setDebug( boolean debug ) {
this.debug = debug;
}
public void debug( String message ) {
if( debug ) {
// only print if debug is true
System.out.println( "DEBUG: " + message );
}
}
public void error( String message ) {
// always print out errors
System.out.println( "ERROR: " + message );
}
}
Utilisation de SystemTrace
 Ajouter les instructions de déverminage nécessaires pour tracer sur
la console chacun des appels de méthodes d’une classe.
class SomeClass {
//... some code ...
SystemTrace log = new SystemTrace();
//... code ...
log.setDebug(true);
log.debug( "entering log" );
// ... etc ...
void getValue(){
log.debug( "entering getValue" );
// ... etc ...
Écrire une classe FileTrace qui implémente Trace.
Les instances de cette classe affiche le résultat dans un fichier.
public class FileTrace implements Trace {
private java.io.PrintWriter pw;
private boolean debug;
public FileTrace() throws java.io.IOException {
}
String fileName = "c:\trace.log" ;
pw = new java.io.PrintWriter( new java.io.FileWriter(fileName ));
public void setDebug( boolean debug ) {this.debug = debug;
}
public void debug( String message ) {
if( debug ) { // only print if debug is true
pw.println( "DEBUG: " + message );
pw.flush();
}
}
public void error( String message ) {
// always print out errors
pw.println( "ERROR: " + message );
pw.flush();
}
}
Paramétrer le programme
 Le nom de ce fichier sera spécifié dans les
propriétés du programme et chargé dans
une instance de ProgramProperties.
 Cette instance sera un Singleton créé à sa
première utilisation. Cette classe sera
sous-classe de java.util.Properties.
/*
public class ProgramProperties extends Properties {
final static public String DEFAULT_FILE_NAME = "defaultProperties";
final static public String PROPS_FILE_NAME = "ex4.properties";
static private ProgramProperties instance__;
static synchronized public ProgramProperties getInstance() {
if (instance__ == null) {
// create and load default properties
ProgramProperties defaultProps = new ProgramProperties();
FileInputStream in;
try {
in = new FileInputStream(DEFAULT_FILE_NAME);
defaultProps.load(in);
in.close();
}
catch (FileNotFoundException e2) {e2.printStackTrace();
}
catch (IOException e3) {e3.printStackTrace();
}
// create program properties with default
ProgramProperties applicationProps;
applicationProps = new ProgramProperties(defaultProps);
try {
// now load properties from last invocation
in = new FileInputStream(PROPS_FILE_NAME);
applicationProps.load(in);
try {
in.close();
}
catch (FileNotFoundException e) {e.printStackTrace();
}
}
catch (IOException e1) { e1.printStackTrace();
}
instance__ = applicationProps;
} // end if (instance__ == null)
return instance__;
}
private ProgramProperties(ProgramProperties defaultProps){
super(defaultProps);
}
}
public FileTrace() throws java.io.IOException {
ProgramProperties props = ProgramProperties.getInstance();
props.getProperty(FILE_NAME_PROPERTY,
FILE_NAME_PROPERTY_DEFAULT );
_pw = new PrintWriter( new FileWriter( getFileName() ) );
}
 Pour utiliser FileTrace au lieu de SystemTrace
 il faut modifier le programme en plusieurs endroits dans
plusieurs classes
 Afin de rassembler la création du système de trace
en un seul endroit,
 écrire une classe TraceFactory possédant une méthode
« factory » abstraite getTrace()
public abstract class TraceFactory {
static private TraceFactory instance__;
static synchronized public TraceFactory getInstance()
if (instance__ == null)
instance__ = createFactory();
return instance__;
}
{
private static TraceFactory createFactory() {
ProgramProperties props = ProgramProperties.getInstance();
if (getProperty("trace.file") != null)
return new FileTraceFactory();
return new SystemTraceFactory();
}
public abstract Trace getTrace();
}
Le if n’est pas très élégant, ni flexible
private static TraceFactory createFactory () {
ProgramProperties props; String FactoryClassName;
TraceFactory factory;
props = ProgramProperties.getInstance();
FactoryClassName = props.getProperty("trace.factory",
"SystemTraceFactory");
factory = new SystemTraceFactory(); // valeur par défaut
try {
factory = (TraceFactory)
Class.forName(FactoryClassName).newInstance();
} catch (InstantiationException e) { e.printStackTrace();
} catch (IllegalAccessException e) { e.printStackTrace();
} catch (ClassNotFoundException e) { e.printStackTrace();
}
return factory;
}
public class SystemTraceFactory extends TraceFactory {
public Trace getTrace() {
return new SystemTrace();
}
}
public class FileTraceFactory extends TraceFactory {
public Trace getTrace() {
try {
return new FileTrace();
} catch (IOException e) { e.printStackTrace();
}
// pour au moins rendre de quoi faire la trace
return new SystemTrace();
}
}
Téléchargement