Abstract Factory Design Java
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
0
down vote
favorite
I am new to Design Pattern implementation and would like to strongly solidify my knowledge to become as good of a programmer as I can. Is this a proper implementation of the Abstract Factory design? The idea here is that I can interchangeably utilize either a ConsoleLogger or a FileLogger for three different "levels" of logging (Execution, Output, and Error). I want the client to be able to log Execution and Output to console, but Error logs to a file if necessary.
Logger Interface:
public interface ILogger
public void log(String content);
Base Logging Factory:
import java.util.HashMap;
public abstract class LoggingFactory
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
public abstract ILogger getLogger();
public static void register(String type, LoggingFactory factory)
factoryMap.put(type, factory);
public static LoggingFactory getFactory(String type)
return factoryMap.get(type);
ConsoleOutputLoggingFactory:
public class ConsoleOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleOutputLoggingFactory", new ConsoleOutputLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleOutputLogger();
ConsoleOutputLogger:
public class ConsoleOutputLoggerimplements ILogger
@Override
public void log(String content)
System.out.println("ConsoleOutputLogger " + content);
FileOutputLoggingFactory:
public class FileOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileOutputLoggingFactory", new FileOutputLoggingFactory());
@Override
public ILogger getLogger()
return new FileOutputLogger();
FileOutputLogger:
public class FileOutputLogger implements ILogger
@Override
public void log(String content)
//write output to file
ConsoleErrorLoggingFactory:
public class ConsoleErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleErrorLoggingFactory", new ConsoleErrorLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleErrorLogger();
ConsoleErrorLogger:
public class ConsoleErrorLogger implements ILogger
@Override
public void log(String content)
System.out.println("ConsoleErrorLogger" + content);
FileErrorLoggingFactory:
public class FileErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileErrorLoggingFactory", new FileErrorLoggingFactory());
@Override
public ILogger getLogger()
return new FileErrorLogger();
FileErrorLogger:
public class FileErrorLogger implements ILogger
@Override
public void log(String content)
//write error to file
Factory Initializer:
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
Main:
public class AbstractFactoryExample
public static void main(String args)
new LoggingInitializer();
ILogger outputLogger = LoggingFactory.getFactory("OutputLogger").getLogger();
if (outputLogger != null)
outputLogger.log("Hello World");
java abstract-factory
add a comment |Â
up vote
0
down vote
favorite
I am new to Design Pattern implementation and would like to strongly solidify my knowledge to become as good of a programmer as I can. Is this a proper implementation of the Abstract Factory design? The idea here is that I can interchangeably utilize either a ConsoleLogger or a FileLogger for three different "levels" of logging (Execution, Output, and Error). I want the client to be able to log Execution and Output to console, but Error logs to a file if necessary.
Logger Interface:
public interface ILogger
public void log(String content);
Base Logging Factory:
import java.util.HashMap;
public abstract class LoggingFactory
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
public abstract ILogger getLogger();
public static void register(String type, LoggingFactory factory)
factoryMap.put(type, factory);
public static LoggingFactory getFactory(String type)
return factoryMap.get(type);
ConsoleOutputLoggingFactory:
public class ConsoleOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleOutputLoggingFactory", new ConsoleOutputLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleOutputLogger();
ConsoleOutputLogger:
public class ConsoleOutputLoggerimplements ILogger
@Override
public void log(String content)
System.out.println("ConsoleOutputLogger " + content);
FileOutputLoggingFactory:
public class FileOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileOutputLoggingFactory", new FileOutputLoggingFactory());
@Override
public ILogger getLogger()
return new FileOutputLogger();
FileOutputLogger:
public class FileOutputLogger implements ILogger
@Override
public void log(String content)
//write output to file
ConsoleErrorLoggingFactory:
public class ConsoleErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleErrorLoggingFactory", new ConsoleErrorLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleErrorLogger();
ConsoleErrorLogger:
public class ConsoleErrorLogger implements ILogger
@Override
public void log(String content)
System.out.println("ConsoleErrorLogger" + content);
FileErrorLoggingFactory:
public class FileErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileErrorLoggingFactory", new FileErrorLoggingFactory());
@Override
public ILogger getLogger()
return new FileErrorLogger();
FileErrorLogger:
public class FileErrorLogger implements ILogger
@Override
public void log(String content)
//write error to file
Factory Initializer:
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
Main:
public class AbstractFactoryExample
public static void main(String args)
new LoggingInitializer();
ILogger outputLogger = LoggingFactory.getFactory("OutputLogger").getLogger();
if (outputLogger != null)
outputLogger.log("Hello World");
java abstract-factory
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I am new to Design Pattern implementation and would like to strongly solidify my knowledge to become as good of a programmer as I can. Is this a proper implementation of the Abstract Factory design? The idea here is that I can interchangeably utilize either a ConsoleLogger or a FileLogger for three different "levels" of logging (Execution, Output, and Error). I want the client to be able to log Execution and Output to console, but Error logs to a file if necessary.
Logger Interface:
public interface ILogger
public void log(String content);
Base Logging Factory:
import java.util.HashMap;
public abstract class LoggingFactory
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
public abstract ILogger getLogger();
public static void register(String type, LoggingFactory factory)
factoryMap.put(type, factory);
public static LoggingFactory getFactory(String type)
return factoryMap.get(type);
ConsoleOutputLoggingFactory:
public class ConsoleOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleOutputLoggingFactory", new ConsoleOutputLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleOutputLogger();
ConsoleOutputLogger:
public class ConsoleOutputLoggerimplements ILogger
@Override
public void log(String content)
System.out.println("ConsoleOutputLogger " + content);
FileOutputLoggingFactory:
public class FileOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileOutputLoggingFactory", new FileOutputLoggingFactory());
@Override
public ILogger getLogger()
return new FileOutputLogger();
FileOutputLogger:
public class FileOutputLogger implements ILogger
@Override
public void log(String content)
//write output to file
ConsoleErrorLoggingFactory:
public class ConsoleErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleErrorLoggingFactory", new ConsoleErrorLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleErrorLogger();
ConsoleErrorLogger:
public class ConsoleErrorLogger implements ILogger
@Override
public void log(String content)
System.out.println("ConsoleErrorLogger" + content);
FileErrorLoggingFactory:
public class FileErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileErrorLoggingFactory", new FileErrorLoggingFactory());
@Override
public ILogger getLogger()
return new FileErrorLogger();
FileErrorLogger:
public class FileErrorLogger implements ILogger
@Override
public void log(String content)
//write error to file
Factory Initializer:
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
Main:
public class AbstractFactoryExample
public static void main(String args)
new LoggingInitializer();
ILogger outputLogger = LoggingFactory.getFactory("OutputLogger").getLogger();
if (outputLogger != null)
outputLogger.log("Hello World");
java abstract-factory
I am new to Design Pattern implementation and would like to strongly solidify my knowledge to become as good of a programmer as I can. Is this a proper implementation of the Abstract Factory design? The idea here is that I can interchangeably utilize either a ConsoleLogger or a FileLogger for three different "levels" of logging (Execution, Output, and Error). I want the client to be able to log Execution and Output to console, but Error logs to a file if necessary.
Logger Interface:
public interface ILogger
public void log(String content);
Base Logging Factory:
import java.util.HashMap;
public abstract class LoggingFactory
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
public abstract ILogger getLogger();
public static void register(String type, LoggingFactory factory)
factoryMap.put(type, factory);
public static LoggingFactory getFactory(String type)
return factoryMap.get(type);
ConsoleOutputLoggingFactory:
public class ConsoleOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleOutputLoggingFactory", new ConsoleOutputLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleOutputLogger();
ConsoleOutputLogger:
public class ConsoleOutputLoggerimplements ILogger
@Override
public void log(String content)
System.out.println("ConsoleOutputLogger " + content);
FileOutputLoggingFactory:
public class FileOutputLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileOutputLoggingFactory", new FileOutputLoggingFactory());
@Override
public ILogger getLogger()
return new FileOutputLogger();
FileOutputLogger:
public class FileOutputLogger implements ILogger
@Override
public void log(String content)
//write output to file
ConsoleErrorLoggingFactory:
public class ConsoleErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("ConsoleErrorLoggingFactory", new ConsoleErrorLoggingFactory());
@Override
public ILogger getLogger()
return new ConsoleErrorLogger();
ConsoleErrorLogger:
public class ConsoleErrorLogger implements ILogger
@Override
public void log(String content)
System.out.println("ConsoleErrorLogger" + content);
FileErrorLoggingFactory:
public class FileErrorLoggingFactory extends LoggingFactory
static
LoggingFactory.register("FileErrorLoggingFactory", new FileErrorLoggingFactory());
@Override
public ILogger getLogger()
return new FileErrorLogger();
FileErrorLogger:
public class FileErrorLogger implements ILogger
@Override
public void log(String content)
//write error to file
Factory Initializer:
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
Main:
public class AbstractFactoryExample
public static void main(String args)
new LoggingInitializer();
ILogger outputLogger = LoggingFactory.getFactory("OutputLogger").getLogger();
if (outputLogger != null)
outputLogger.log("Hello World");
java abstract-factory
asked Feb 8 at 18:19
Hans Landa
1
1
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
can be simplified to the following without any changes in functionality:
private static final Map<String, LoggingFactory> factoryMap = new HashMap<>();
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
The initialization of a class only happens in it's initializer blocks. Nowhere else.
What you're doing here is wiring up dependencies. Use a DI framework for that ...
If you were going to set up the factories this way in the first place, you could've just not have them register themselves. It's weird that they register themselves anyways. That results in the following changes:
- LoggerFactory implementations don't need to be derived from
LoggingFactory
to have access to thefactoryMap
, only to conform to thegetLogger
interface. - Actually the
getLogger
interface is what you'd have in a functional interface in modern Java.
This results in simplifications to your API. Instead of explicitly constructing factories and using getFactory
, you're off much better hiding the implementation detail of Factories and instead using a Facade, like so:
public static final class LoggingFactory
private static final Map<String, Supplier<ILogger>> factoryMap = new HashMap<>();
static
ILogger consoleOutLoggerSingleton = new ConsoleOutputLogger();
factoryMap.put("ConsoleOutputLogger", () -> consoleOutputLoggerSingleton);
ILogger fileOutputLoggerSingleton = new FileOutputLogger();
factoryMap.put("FileOutputLogger", () -> fileOutputLoggerSingleton);
ILogger consoleErrorLoggerSingleton = new ConsoleErrorLogger();
factoryMap.put("ConsoleErrorLogger", () -> consoleErrorLoggerSingleton);
ILogger fileErrorLoggerSingleton = new FileErrorLogger();
factoryMap.put("FileErrorLogger", () -> fileErrorLoggerSingleton);
public static ILogger getLoggerFor(String name)
return factoryMap.getOrDefault(name, () -> new NoOpLogger()).get();
This cuts away the "man in the middle" of your factory, not to mention the initialization outside the class. It also is more in line with usual Java logging APIs, where you directly obtain the logger.
In closing you should be aware that reinventing logging is usually a "Bad Ideaâ¢". If this hadn't been prefixed, I'd have washed your head for it :)
Finally: Just because there is a factory, the client of you API doesn't need to know- Generally the less indirection your API has, the easier it will be to use. Strive to minimize ways through your API.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
can be simplified to the following without any changes in functionality:
private static final Map<String, LoggingFactory> factoryMap = new HashMap<>();
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
The initialization of a class only happens in it's initializer blocks. Nowhere else.
What you're doing here is wiring up dependencies. Use a DI framework for that ...
If you were going to set up the factories this way in the first place, you could've just not have them register themselves. It's weird that they register themselves anyways. That results in the following changes:
- LoggerFactory implementations don't need to be derived from
LoggingFactory
to have access to thefactoryMap
, only to conform to thegetLogger
interface. - Actually the
getLogger
interface is what you'd have in a functional interface in modern Java.
This results in simplifications to your API. Instead of explicitly constructing factories and using getFactory
, you're off much better hiding the implementation detail of Factories and instead using a Facade, like so:
public static final class LoggingFactory
private static final Map<String, Supplier<ILogger>> factoryMap = new HashMap<>();
static
ILogger consoleOutLoggerSingleton = new ConsoleOutputLogger();
factoryMap.put("ConsoleOutputLogger", () -> consoleOutputLoggerSingleton);
ILogger fileOutputLoggerSingleton = new FileOutputLogger();
factoryMap.put("FileOutputLogger", () -> fileOutputLoggerSingleton);
ILogger consoleErrorLoggerSingleton = new ConsoleErrorLogger();
factoryMap.put("ConsoleErrorLogger", () -> consoleErrorLoggerSingleton);
ILogger fileErrorLoggerSingleton = new FileErrorLogger();
factoryMap.put("FileErrorLogger", () -> fileErrorLoggerSingleton);
public static ILogger getLoggerFor(String name)
return factoryMap.getOrDefault(name, () -> new NoOpLogger()).get();
This cuts away the "man in the middle" of your factory, not to mention the initialization outside the class. It also is more in line with usual Java logging APIs, where you directly obtain the logger.
In closing you should be aware that reinventing logging is usually a "Bad Ideaâ¢". If this hadn't been prefixed, I'd have washed your head for it :)
Finally: Just because there is a factory, the client of you API doesn't need to know- Generally the less indirection your API has, the easier it will be to use. Strive to minimize ways through your API.
add a comment |Â
up vote
1
down vote
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
can be simplified to the following without any changes in functionality:
private static final Map<String, LoggingFactory> factoryMap = new HashMap<>();
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
The initialization of a class only happens in it's initializer blocks. Nowhere else.
What you're doing here is wiring up dependencies. Use a DI framework for that ...
If you were going to set up the factories this way in the first place, you could've just not have them register themselves. It's weird that they register themselves anyways. That results in the following changes:
- LoggerFactory implementations don't need to be derived from
LoggingFactory
to have access to thefactoryMap
, only to conform to thegetLogger
interface. - Actually the
getLogger
interface is what you'd have in a functional interface in modern Java.
This results in simplifications to your API. Instead of explicitly constructing factories and using getFactory
, you're off much better hiding the implementation detail of Factories and instead using a Facade, like so:
public static final class LoggingFactory
private static final Map<String, Supplier<ILogger>> factoryMap = new HashMap<>();
static
ILogger consoleOutLoggerSingleton = new ConsoleOutputLogger();
factoryMap.put("ConsoleOutputLogger", () -> consoleOutputLoggerSingleton);
ILogger fileOutputLoggerSingleton = new FileOutputLogger();
factoryMap.put("FileOutputLogger", () -> fileOutputLoggerSingleton);
ILogger consoleErrorLoggerSingleton = new ConsoleErrorLogger();
factoryMap.put("ConsoleErrorLogger", () -> consoleErrorLoggerSingleton);
ILogger fileErrorLoggerSingleton = new FileErrorLogger();
factoryMap.put("FileErrorLogger", () -> fileErrorLoggerSingleton);
public static ILogger getLoggerFor(String name)
return factoryMap.getOrDefault(name, () -> new NoOpLogger()).get();
This cuts away the "man in the middle" of your factory, not to mention the initialization outside the class. It also is more in line with usual Java logging APIs, where you directly obtain the logger.
In closing you should be aware that reinventing logging is usually a "Bad Ideaâ¢". If this hadn't been prefixed, I'd have washed your head for it :)
Finally: Just because there is a factory, the client of you API doesn't need to know- Generally the less indirection your API has, the easier it will be to use. Strive to minimize ways through your API.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
can be simplified to the following without any changes in functionality:
private static final Map<String, LoggingFactory> factoryMap = new HashMap<>();
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
The initialization of a class only happens in it's initializer blocks. Nowhere else.
What you're doing here is wiring up dependencies. Use a DI framework for that ...
If you were going to set up the factories this way in the first place, you could've just not have them register themselves. It's weird that they register themselves anyways. That results in the following changes:
- LoggerFactory implementations don't need to be derived from
LoggingFactory
to have access to thefactoryMap
, only to conform to thegetLogger
interface. - Actually the
getLogger
interface is what you'd have in a functional interface in modern Java.
This results in simplifications to your API. Instead of explicitly constructing factories and using getFactory
, you're off much better hiding the implementation detail of Factories and instead using a Facade, like so:
public static final class LoggingFactory
private static final Map<String, Supplier<ILogger>> factoryMap = new HashMap<>();
static
ILogger consoleOutLoggerSingleton = new ConsoleOutputLogger();
factoryMap.put("ConsoleOutputLogger", () -> consoleOutputLoggerSingleton);
ILogger fileOutputLoggerSingleton = new FileOutputLogger();
factoryMap.put("FileOutputLogger", () -> fileOutputLoggerSingleton);
ILogger consoleErrorLoggerSingleton = new ConsoleErrorLogger();
factoryMap.put("ConsoleErrorLogger", () -> consoleErrorLoggerSingleton);
ILogger fileErrorLoggerSingleton = new FileErrorLogger();
factoryMap.put("FileErrorLogger", () -> fileErrorLoggerSingleton);
public static ILogger getLoggerFor(String name)
return factoryMap.getOrDefault(name, () -> new NoOpLogger()).get();
This cuts away the "man in the middle" of your factory, not to mention the initialization outside the class. It also is more in line with usual Java logging APIs, where you directly obtain the logger.
In closing you should be aware that reinventing logging is usually a "Bad Ideaâ¢". If this hadn't been prefixed, I'd have washed your head for it :)
Finally: Just because there is a factory, the client of you API doesn't need to know- Generally the less indirection your API has, the easier it will be to use. Strive to minimize ways through your API.
static
factoryMap = new HashMap<String, LoggingFactory>();
private static HashMap<String, LoggingFactory> factoryMap;
can be simplified to the following without any changes in functionality:
private static final Map<String, LoggingFactory> factoryMap = new HashMap<>();
public class LoggingInitializer
public LoggingInitializer()
LoggingFactory.register("ConsoleOutputLogger", new ConsoleOutputLoggingFactory());
LoggingFactory.register("FileOutputLogger", new FileOutputLoggingFactory());
LoggingFactory.register("ConsoleErrorLogger", new ConsoleErrorLoggingFactory());
LoggingFactory.register("FileErrorLogger", new FileErrorLoggingFactory());
The initialization of a class only happens in it's initializer blocks. Nowhere else.
What you're doing here is wiring up dependencies. Use a DI framework for that ...
If you were going to set up the factories this way in the first place, you could've just not have them register themselves. It's weird that they register themselves anyways. That results in the following changes:
- LoggerFactory implementations don't need to be derived from
LoggingFactory
to have access to thefactoryMap
, only to conform to thegetLogger
interface. - Actually the
getLogger
interface is what you'd have in a functional interface in modern Java.
This results in simplifications to your API. Instead of explicitly constructing factories and using getFactory
, you're off much better hiding the implementation detail of Factories and instead using a Facade, like so:
public static final class LoggingFactory
private static final Map<String, Supplier<ILogger>> factoryMap = new HashMap<>();
static
ILogger consoleOutLoggerSingleton = new ConsoleOutputLogger();
factoryMap.put("ConsoleOutputLogger", () -> consoleOutputLoggerSingleton);
ILogger fileOutputLoggerSingleton = new FileOutputLogger();
factoryMap.put("FileOutputLogger", () -> fileOutputLoggerSingleton);
ILogger consoleErrorLoggerSingleton = new ConsoleErrorLogger();
factoryMap.put("ConsoleErrorLogger", () -> consoleErrorLoggerSingleton);
ILogger fileErrorLoggerSingleton = new FileErrorLogger();
factoryMap.put("FileErrorLogger", () -> fileErrorLoggerSingleton);
public static ILogger getLoggerFor(String name)
return factoryMap.getOrDefault(name, () -> new NoOpLogger()).get();
This cuts away the "man in the middle" of your factory, not to mention the initialization outside the class. It also is more in line with usual Java logging APIs, where you directly obtain the logger.
In closing you should be aware that reinventing logging is usually a "Bad Ideaâ¢". If this hadn't been prefixed, I'd have washed your head for it :)
Finally: Just because there is a factory, the client of you API doesn't need to know- Generally the less indirection your API has, the easier it will be to use. Strive to minimize ways through your API.
answered Feb 9 at 1:56
Vogel612â¦
20.9k345124
20.9k345124
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187109%2fabstract-factory-design-java%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password