I try to understand the SOLID principles and therefore implemented some java snippets. My concern is the OCP at the moment. Having following samples,
public abstract class Bakery
{
public abstract Bakegood bake();
}
/******************************************/
public class BreadBakery extends Bakery {
#Override
public Bakegood bake() {
return new Bread();
}
}
/******************************************/
public class CakeBakery extends Bakery {
#Override
public Bakegood bake() {
return new Cake();
}
}
/******************************************/
how can I create the right bakery. Assume a customer comes to the bakery and says: "I'd have two cakes, please!", how can I then instantiate the CakeBakery. Of course I can create an abstract factory like:
public static Bakery createBakery(final String orderedBakegood)
{
switch(bakegood)
{
case "Cake": return new CakeBakery();
case "Bread": return new BreadBakery();
default: throw new InvalidBakeryException();
}
}
But I don't want to use switch or if statements. Is there any other possibility or am I completely wrong with the understanding?
Open/closed principle says:
Software entities (classes, modules, functions, etc.) should be open
for extension, but closed for modification.
So whenever you introduce a new Bakery, you should not modify existing code. You can use something like a registry for your Bakery classes. If you need to add a new Bakery, just extend Bakery class and register it (e.g. at startup). Hence no "if" or "switch" modification is required. Moreover, adding a new Bakery does not require changing the internals of the registry or the code that is calling the registry.
Furthermore, this technique is not dependent on the way you register your components. You can do it programatically, with a configuration file (xml, ...), via classpath scanning, ...
You can see this approach in the Spring framework a lot. Basically the Spring framework is a great source of many design principles.
Here you can see a very simple registry implementation.
public class BakeryRegistry {
private Map<String, Bakery> mapping = new HashMap<>();
public BakeryRegistry() {
loadDefaultMappingFromConfigFile();
}
public Bakery getBakery(String name) {
return mapping.get(name);
}
public void registerBakery(String name, Bakery bakery) {
mapping.put(name, bakery);
}
private void loadDefaultMappingFromConfigFile() {
...
}
}
Maybe article Killing Switch Statements With A Registry can help. It is based on JavaScript but the principle is the same.
The contrived abstraction is causing the problem here. Customers will not ask the bakery for abstract "baked goods", because all baked goods are not substitutable. Bread is not a substitute for cake, and vice versa. Wrapping these two different products into one inheritance hierarchy is a violation of the Liskov Substitution Principle.
The SOLID principles are interrelated, so applying OCP will be difficult or impossible without applying LSP first. See the introduction to LSP where Robert Martin describes inheritance as being critical to OCP, and goes on to describe LSP as being critical to inheritance.
Related
I'm currently working on a project that involves creating an abstraction layer. The goal of the project is to support multiple implementations of server software in the event that I might need to switch over to it. The list of features to be abstracted is rather long, so I'm going to want to look into a rather painless way to do it.
Other applications will be able to interact with my project and make calls that will eventually boil down to being passed to the server I'm using.
Herein lies the problem. I haven't much experience in this area and I'm really not sure how to make this not become a sandwich of death. Here's a chain of roughly what it's supposed to look like (and what I'm trying to accomplish).
/*
Software that is dependent on mine
|
Public API layer (called by other software)
|
Abstraction between API and my own internal code (this is the issue)
|
Internal code (this gets replaced per-implementation, as in, each implementation needs its own layer of this, so it's a different package of entirely different classes for each implementation)
|
The software I'm actually using to write this (which is called by the internal code)
*/
The abstraction layer (the one in the very middle, obviously) is what I'm struggling to put together.
Now, I'm only stuck on one silly aspect. How can I possibly make the abstraction layer something that isn't a series of
public void someMethod() {
if(Implementation.getCurrentImplementation() == Implementation.TYPE1) {
// whatever we need to do for this specific implementation
else {
throw new NotImplementedException();
}
}
(forgive the pseudo-code; also, imagine the same situation but for a switch/case since that's probably better than a chain of if's for each method) for each and every method in each and every abstraction-level class.
This seems very elementary but I can't come up with a logical solution to address this. If I haven't explained my point clearly, please explain with what I need to elaborate on. Maybe I'm thinking about this whole thing wrong?
Why not using inversion of control ?
You have your set of abstractions, you create several implementations, and then you configure your public api to use one of the implementations.
Your API is protected by the set of interfaces that the implementations inherit. You can add new implementations later without modifying the API code, and you can switch even at runtime.
I don't know anymore if inversion of control IS dependency injection, or if DI is a form of Ioc but... it's just that you remove the responsibility of dependency management from your component.
Here, you are going to have
API layer (interface that the client uses)
implementations (infinite)
wrapper (that does the IoC by bringing the impl)
API layer:
// my-api.jar
public interface MyAPI {
String doSomething();
}
public interface MyAPIFactory {
MyAPI getImplementationOfMyAPI();
}
implementations:
// red-my-api.jar
public class RedMyAPI implements MyAPI {
public String doSomething() {
return "red";
}
}
// green-my-api.jar
public class GreenMyAPI implements MyAPI {
public String doSomething() {
return "green";
}
}
// black-my-api.jar
public class BlackMyAPI implements MyAPI {
public String doSomething() {
return "black";
}
}
Some wrapper provide a way to configure the right implementation. Here, you can hide your switch case in the factory, or load the impl from a config.
// wrapper-my-api.jar
public class NotFunnyMyAPIFactory implements MyAPIFactory {
private Config config;
public MyAPI getImplementationOfMyAPI() {
if (config.implType == GREEN) {
return new GreenMyAPI();
} else if (config.implType == BLACK) {
return new BlackMyAPI();
} else if (config.implType == RED) {
return new RedMyAPI();
} else {
// throw...
}
}
}
public class ReflectionMyAPIFactory implements MyAPIFactory {
private Properties prop;
public MyAPI getImplementationOfMyAPI() {
return (MyAPI) Class.forName(prop.get('myApi.implementation.className'))
}
}
// other possible strategies
The factory allows to use several strategies to load the class. Depending on the solution, you only have to add a new dependency and change a configuration (and reload the app... or not) to change the implementation.
You might want to test the performances as well.
If you use Spring, you can only use the interface in your code, and you inject the right implementation from a configuration class (Spring is a DI container). But no need to use Spring, you can do that on the Main entry point directly (you inject from the nearest of your entry point).
The my-api.jar does not have dependencies (or maybe some towards the internal layers).
All the jar for implementations depend on my-api.jar and on you internal code.
The wrapper jar depends on my-api.jar and on some of the impl jar.
So the client load the jar he wants, use the factory he wants or a configuration that inject the impl, and use your code. It depends also on how you expose your api.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I implemented a class Database Manager that manages operations on two database engines. The class has a private variable databaseEngine which is set before using class methods (drop database, create database, run script, compare, disconnect, etc.) and based on this variable the class recognizes how to behave.
However, and I know it's wrong, Database Manager's methods are full of switch cases like this one:
public void CreateNewDatabase(String databaseName){
switch (databaseEngine){
case "mysql":
//Executes a prepared statement for dropping mysql database (databaseName
break;
case "postgres":
//Executes a prepared statement for dropping postgres database (databaseName
break;
...
}
}
I require a good advice about this. I want to load everything from configuration and resources folders, I mean, the prepared statement for creating and dropping, etc. If a new database engine needs to be supported, it won't be a headache as It would just require to save sql sripts in a resources file and any other data in a configuration file. Please, suggest me any design pattern useful for this case.
Whenever you need to invoke different operations based on a switch statement, think about using an abstract class which defines the operation interface and implementation classes which implement the operation.
In your case databaseEngine is a String which names a database. Instead create an abstract class DatabaseEngine and define operations like createDatabase:
public abstract class DatabaseEngine {
public abstract void createDatabase(String databaseName);
public abstract void dropDatabase(String databaseName);
}
and add implementations:
public class PostgresEngine extends DatabaseEngine {
public void createDatabase(String databaseName) {
... // do it the postgres way
}
}
and then use it in your manager class
public void createNewDatabase(String databaseName) {
engine_.createDatabase(databaseName);
}
First thing: switching on strings is so old school; if at all; you would want to use a true enum for that. But of course, that isn't really the point; and switching over enums is as bad as switching over strings (regarding the thing that you have in mind) from a "OO design" point of view.
The solution by wero is definitely the "correct choice" from an OO perspective. You see, good OO design starts with SOLID; and SOLID starts with SRP.
In this case, I would point out the "there is only one reason to change" aspect of SRP. Thing is: if you push all database handling for 2, 3, n different databases into one class ... that means that you have to change that one class if any of your databases requires a change. Besides the obvious: providing "access means" to ONE database is (almost more) than enough of a "single responsibility" for a single class.
Another point of view: this is about balancing. Either you are interested in a good, well structured, "really OO type of" design ... then you have to bite the bullet and either define an interface or abstract base class; that is then implemented/extended differently for each concrete database.
Or you prefer "stuffing everything into one class" ... then just keep what you have, because it really doesn't matter if you use door handles made out of gold or steel ... for a house that was built on a bad basement anyway.
Meaning: your switch statements are just the result of a less-than-optimal design. Now decide if you want to cure the symptom or the root cause of the problem.
I implemented a class Database Manager that manages operations on two database engines.
What if you had three or four or five different databases/storages? For example, Oracle, MongoDB, Redis, etc. Would you still put implementation for all of them into Database Manager?
Database Manager's methods are full of switch cases...
As expected, because you put everything into one class.
Please, suggest me any design pattern useful for this case.
The most straitforward way to simplify your solution would be to separate MySQL and Postgree implementations from each other. You would need to use Factory and Strategy design patterns. If one sees a switch, one should consider using them, but don't be obsessed with patterns. They are NOT your goal, i.e. don't put them everywhere in your code just because you can.
So, you should start from defining your abstractions. Create an interface or an abstract class if there's a functionality common to all database subclasses.
// I'm not sure what methods you need, so I just added methods you mentioned.
public interface MyDatabase {
void drop();
void create();
void runScript();
void compare();
void disconnect();
}
Then you need to implement your databases which in fact are strategies.
public final class MySqlDatabase implements MyDatabase {
#Override
public void drop() {}
...
}
public final class PostgreDatabase implements MyDatabase {
#Override
public void drop() {}
...
}
Finally you need to create a factory. You can make it static or implement an interface if you like.
public class MyDatabaseFactory {
public MyDatabase create(String type) {
switch (type) {
case "mysql":
return new MySqlDatabase();
case "postgress":
return new PostgreDatabase();
default:
throw new IllegalArgumentException();
}
}
}
You don't necessarily have to pass a string. It can be an option/settings class, but they have a tendency to grow which may lead to bloated classes. But don't worry too much about it, it's not your biggest problem at the moment.
Last, but not least. If you don't mind, revise your naming conventions. Please, don't name your classes as managers or helpers.
You could create an abstract base class for your DatabaseEngines like this:
public abstract class DatabaseEngine {
public abstract void createDatabase(final String databaseName);
public abstract void dropDatabase(final String databaseName);
}
And then create concrete implementations for each DatabaseEngine you are supporting:
public final class MySQLEngine extends DatabaseEngine {
#Override
public void createDatabase(final String databaseName) {
}
#Override
public void dropDatabase(final String databaseName) {
}
}
Then when you want to make a call to create/drop it will look more like this:
databaseEngine.createDatabase("whatever");
This is opinion based question: but in my point of view you can use:
Factory Design pattern. This will take care of any other
database added or changed in future.
Example:
public interface IDataBaseEngine {
...
}
public class OracleDBConnection implements IDataBaseEngine {
...
}
public class MySQLDBConnection implements IDataBaseEngine {
....
}
public class DatabaseEngineFactory {
public IDataBaseEngine getDatabaseConnection() {
....
}
}
Second, create files let say xml files which will contains your SQL
and according to your DB (which can be configured) these files will
be converted to its SQL
Example:
SQL file: customer.table
<TABLE>
<SELECT>
<FROM>customer</FROM>
<WHERE>customer_id = ?</WHERE>
<ORDER_BY>customer_id<ORDER_BY>
</SELECT>
</TABLE>
Now if your configuration file says your database is oracle, then while compiling above SQL file it will create following SQL file:
SELECT * FROM customer
WHERE customer_id = ?
ORDER BY customer_id
After reading an interesting article, I have a few questions around this. Please refer to Common Pitfall #8: Pretending Java is more like C (i.e. not understanding OOP) on [zero-turn-around]
I agree to the authors solution for the pitfall. I face a similar issue with my code (abuse of instanceof). But I cannot implement the code as the author has suggested. My scenario is as below
I have JMS as a messaging bus.
Messages float around the system. Listener typically listen to the messages.
All the messages have a single parent IMessage.
I use instanceof to distinguish between messages.
The listeners typically do domain specific business logic.
If I agree with the authors solution, I will have to implement domain specific business logic in the Message classes, which I think will bloat my light-weight message objects. Not just that, I will now have many references (composition) in my message objects which I think is unfair as the message objects will now have business (domain) behavior in it.
What is the reasonable solution to this problem? Example code below
public void onMessage(IMessage mssg)
{
if(mssg instanceof MoPn){
...
} else if(mssg instance of MoZn){
...
} else if(mssg instance of MoLn){
...
}
}
One reasonable solution is creating listeners that know to work with specific type of message.
Here is the interface.
interface MessageListener<M extends IMessage> {
void onMessage(M message);
}
Here is a skeleton of one of the classes:
class MoZnListener implements MessageListener<MoZn> {
public void onMessage(MoZn message) {
}
}
Now you can create mapping between messages and listeners. You can use properties file, hard coded map, annotations. It is up to you. Once you have it you can implement one JMS message listener that looks like
class MessageEntryPoint implements MessageListener {
public void onMessage(Message message) {
getMessageHandler(message).onMessage(message.getObject());
}
}
Now your system is extandable. No instanceof. To introduce new message type you just have to create appropriate class that implements IMessage and listener that supports it.
BTW more comments.
Using I as to mark interface is not java-style.
I am not familiar with your domain and probably name like MoPn is self-explainable for you, but IMHO it is not. Try to use more self explainable identifiers.
This might upset some purists, but I believe that using a language with OO features doesn't necessarily mean you have to apply OO to everything.
Messages are simply schema. They carry data. Forcing object-orientation upon structures that merely carry data from one place to another can be an anti-pattern as well.
Separating the logic from the data model is sometimes seen as being against OOP but is sometimes necessary for decoupling. The code sending the message doesn't need to know anything about how to respond to the message.
Some of the other problems with instanceof are that it's hard to find what needs updating when adding a new type, and there's no way to make sure all cases are covered. These problems can be solved by adding some new interfaces:
interface Message {
void callHandler(MessageHandler handler);
}
interface MessageHandler {
default void onMoPn(MoPn message) {
}
default void onMoZn(MoZn message) {
}
}
class MoPn implements Message {
public void callHandler(MessageHandler handler) {
handler.onMoPn(this);
}
}
class Mozn implements Message {
public void callHandler(MessageHandler handler) {
handler.onMoZn(this);
}
}
and add a handler:
class MessageHandlerImpl implements MessageHandler {
public void onMoPn(MoPn message) {
System.out.println("MoPn message: " + message);
}
}
When you get a message, you can call the handler like:
MessageHandler handler = new MessageHandlerImpl()
Message message = new MoPn();
message.callHandler(handler);
In the real world what do people use this for (to solve what types of problems)? Can I see some example code of these working together? All I can find is code about cats and dogs speaking or people drinking milk or coffee...
Do people really implement polymorphism with interfaces? What for?
Sure,
Below is concrete example of the "Observer" pattern, using classes and interfaces to accomplish polymorphic behavior in a logger system:
interface ILogger{
public void handleEvent (String event);
}
class FileLogger implements ILogger{
public void handleEvent (String event){
//write to file
}
}
class ConsoleLogger implements ILogger{
public void handleEvent (String event){
System.out.println( event );
}
}
class Log {
public void registerLogger (ILogger logger){
listeners.add(logger);
}
public void log (String event){
foreach (ILogger logger in listeners){
logger.handleEvent(event); //pass the log string to both ConsoleLogger and FileLogger!
}
}
private ArrayList<ILogger> listeners;
}
Then, you could use it as follows:
public static void main(String [] args){
Log myLog();
FileLogger myFile();
ConsoleLogger myConsole();
myLog.registerLogger( myFile );
myLog.registerLogger( myConsole );
myLog.log("Hello World!!");
myLog.log("Second log event!");
}
Hope this helps your understanding of interfaces and polymorphism.
Map<String,Person> peopleByName = new HashMap<String,Person>();
If, down the road, I decide the memory overhead of HashMap is too much, I can re-do this as a TreeMap, and live with the slightly more expensive lookup times
Map<String,Person> peopleByName = new TreeMap<String,Person>();
Because peopleByName is a Map, not a TreeMap or a HashMap, all my calls are guaranteed to work on either map regardless of implementation.
This is best illustrated with the following example
public class CatsAndDogsDrinkingMilkAndCoffee {
// what, no? :-(
}
interface Request {
Response execute();
}
interface Response {
String serialize();
}
class RequestProcessor {
void processRequest(Request r) {
logger.log("Request: " + r);
Response s = r.execute();
logger.log("Response: " + s);
connectionManager.write(r.serialize());
}
}
Say in this example, RequestProcesor doesn't need to know about implementations of Request and Response
Have a look at the code for Map/AbstractMap/HashMap as an example. You will find thousands of other examples in the JDK source which comes with the JDK (in src.zip)
imagine "somebody" designed a huge program, with lotsa code. suppose that "that somebody" used interfaces in the design of some controller logic. now you are hired to work with this code which youve never seen before. you are asked to design a new controller class. all you need to do now is to implement the interface and make all its methods work.
if that somebody had not used interfaces, then not only would you have to redesign the controller, but you would probably need to redesign potentially the whole project because there is very strong coupling between the controller class and the rest of the classes. this will take you months just to understand the code, not to mention the new set of bugs you would probably introduce..
Almost any Java application with GUI uses it (but of course not only GUI...). For example, look at the source of android VideoView (this is the first comes to my mind...)
Another suggestion I'd have for "the real world" is in using spring batch. If you have a commonly used report format that follows a pattern like "pull data, create report, send to recipients" you can create an interface for your reports that enforces this standard. In this sense it works like a "template" that all batch reports would follow.
A boring example, but it's something I faced in my first year...
Have you wondered how LINQ in .net works ? It's all about Interfaces and polymorphism.
You need to work on projects then you will come to know about all this.
I better explain the question with an example.
I have an Interface Model which can be used to access data.
There can be different implementations of Model which can represent the data in various format say XMl , txt format etc. Model is not concerned with the formats.
Lets say one such implementation is myxmlModel.
Now i want to force myxmlModel and every other implementation of Model to follow Singleton Pattern.The usual way is to make myxmlModels constructor private and provide a static factory method to return an instance of myModel class.But the problem is interface cannot have static method definitions and a result i cannot enforce a particular Factory method definition on all implementation of Model. So one implementation may end with providing getObject() and other may have getNewModel()..
One work around is to allow package access to myxmlModel's constructor and create a Factory class which creates the myxmlModel object and cache it for further use.
I was wondering if there is a better way to achieve the same functionality .
Make a factory that returns
instances of your interface, Model.
Make all concrete implementations of the model package-private classes
in the same package as your factory.
If your model is to be a singleton, and you are using java
5+, use enum instead of traditional
singleton, as it is safer.
public enum MyXMLModel{
INSTANCE();
//rest of class
};
EDIT:
Another possibility is to create delegate classes that do all the work and then use an enum to provide all of the Model Options.
for instance:
class MyXMLModelDelegate implements Model {
public void foo() { /*does foo*/}
...
}
class MyJSONModelDelegate implements Model {
public void foo() { /*does foo*/ }
...
}
public enum Models {
XML(new MyXMLModelDelgate()),
JSON(new MyJSONModelDelegate());
private Model delegate;
public Models(Model delegate) { this.delegate=delegate; }
public void foo() { delegate.foo(); }
}
You can use reflection. Something like this:
public interface Model {
class Singleton {
public static Model instance(Class<? extends Model> modelClass) {
try {
return (Model)modelClass.getField("instance").get(null);
} catch (blah-blah) {
blah-blah
}
}
}
public class XmlModel implements Model {
private static final Model instance = new XmlModel();
private XmlModel() {
}
}
usage:
Model.Singleton.instance(XmlModel.class)
Actually, I don't like this code much :). First, it uses reflection - very slow, second - there are possibilities of runtime errors in case of wrong definitions of classes.
Can you refactor the interface to be an abstract class? This will allow you to force a particular factory method down to all implementing classes.
I used to ask myself the same question. And I proposed the same answer ;-)
Now I normally drop the "forcing" behavior, I rely on documentation.
I found no case where the Singleton aspect was so compelling that it needed to be enforced by all means.
It is just a "best-practice" for the project.
I usually use Spring to instanciate such an object,
and it is the Spring configuration that makes it a Singleton.
Safe, and so easy ... plus additionnal Spring advantages (such as Proxying, substituing a different object once to make some tests etc...)
This is more an answer to your comment/clarification to kts's answer. Is it so, that the real problem is not using the Singleton pattern but instead defining an eclipse (equinox) extension point schema that allows contributing a singleton?
I think, this can't be done, because everytime you call IConfigurationElement.createExecutableExtension you create a new instance. This is quite incompatible with your singleton requirement. And therefore you need the public default constructor so that everybody can create instances.
Unless you can change the extension point definition so that plugins contribute a ModelFactory rather than a model, like
public interface ModelFactory {
public Model getModelInstance();
}
So the extension user will instantiate a ModelFactory and use it to obtain the singleton.
If I guessed wrong, leave a comment and I delete the answer ;)