Today, we are tackling something that is kind of new (and by that, I mean not mentioned in the GoF book), and that is the Event Bus.
Imagine having a large scale application containing a lot of components interacting with each other, and you want a way to make your components communicate while maintaining loose coupling and separation of concerns principles, the Event Bus pattern can be a good solution for your problem.
This blog post is mainly inspired by the works of Martin Fowler and Eric Evans in their seminal paper Specifications
I find this pattern interesting as it remedies years of head bashing and hair pulling for finding ways of isolating the evolution of a domain model from the mechanisms involved in inspecting and querying it while maintaining a high level of encapsulation. I like to think of it as a "reflection" on the domain model. Hopefully, things will become clearer as we proceed.
Here I am with another useful design pattern for you — the adapter design pattern. I will also highlight the differences between the decorator design pattern (see my previous article, Decorator Design Pattern in Java, here) and the adapter design pattern.
To better understand this, let’s look at an example of geometric shapes. I am keeping the example relatively simple to keep the focus on the pattern. Suppose we have a project of drawing, in which we are required to develop different kinds of geometric shapes that will be used in the
Drawing via a common interface called
Shape.
Any successful programming language lives on long after it is first created. In its lifespan, this language goes through multiple changes that fix different issues as well as adds more and more useful features. In order to go through these changes smoothly, the software should be designed to make it more maintainable and extensible.
Oftentimes, we lack internal quality, and the focus is primarily on "making it work" and not so much on "doing it the right way." Here, I will explain my thoughts on getting software craftsmanship to "do it right" in the object-oriented world.
Here I am with my another article on design patterns. Many of us use strategy as well as factory design patterns. But, sometimes, it becomes really hard to tell the difference between the two and to decide when and which would be a better fit for the project at hand. Let’s take a look at some of the key points for each of these with an example.
The strategy design pattern (also known as the policy design pattern) is a behavioral design pattern that allows us to select an algorithm at runtime. In this pattern, the code receives run-time instructions to decide which group of the algorithms to use.
By using Class-level Member (Lazy Initialization Method), we have various ways of creating singletons in Java. Now, first of all, what is Singleton and why is it required?. There are various ways to design/code a singleton class.
getInstance()method.
public class SingletonClass { private static final SingletonClass SINGLE_INSTANCE = new SingletonClass(); private SingletonClass() {} public static SingletonClass getInstance() { return SINGLE_INSTANCE; } }
public class SingletonClass { private static SingletonClass SINGLE_INSTANCE = null; private SingletonClass() {} public static SingletonClass getInstance() { if (SINGLE_INSTANCE == null) { synchronized(SingletonClass.class) { SINGLE_INSTANCE = new SingletonClass(); } } return SINGLE_INSTANCE; } }
public class SingletonClass { private static SingletonClass SINGLE_INSTANCE = null; private SingletonClass() {} public static SingletonClass getInstance() { if (SINGLE_INSTANCE == null) { synchronized (SingletonClass.class) { if (SINGLE_INSTANCE == null) { SINGLE_INSTANCE = new SingletonClass(); } } } return SINGLE_INSTANCE; } }
public enum SingletonClass { SINGLE_INSTANCE; }
Last week, I spoke at Scalapeño about “Thinking Less With Scala.” The video has just been published and I’m excited to share it with you.
The main message of the talk is that Functional Scala allows you to think less when you read and write code. It demonstrates that good Functions, Signatures, Data, and Functional Patterns to keep your mental stack small.
Watch this talk if you’d like to get started with Functional Programming in Scala, or if you’re already doing some FP but want an insight into the benefits.
In this talk, I answer the following questions about Scala:
Monoid?
catslibrary to take advantage of these patterns?
My slides are available here:
The singleton design pattern is a software design pattern that restricts the instantiation of a class to one object. In comparison with other creational design patterns, such as the abstract factory, the singleton builder pattern will create an object and will also be responsible so that only one instance of that object exists.
When creating a class as a singleton, there are some certain problems to keep in mind:
For example, let’s suppose that we have a class that sends messages — the
Messenger class:
package com.gkatzioura.design.creational.singleton; public class Messenger { public void send(String message) { } }
However, we want the message procedure to be handled only by one instance of the
Messenger class. Let’s imagine a scenario where the
Messenger class opens a tcp connection (for example, XMPP) and has to keep the connection alive in order to send messages. It will be pretty inefficient to open a new XMPP connection each time we have to send a message.
Therefore, we will proceed and make the
Messenger class a singleton.
package com.gkatzioura.design.creational.singleton; public class Messenger { private static Messenger messenger = new Messenger(); private Messenger() {} public static Messenger getInstance() { return messenger; } public void send(String message) { } }
As you can see, we set the messenger constructor as private, and we initialized a messenger using a static variable. Static variables are class level variables where memory allocation only happens once when the class is loaded in the memory. In doing this, we ensure that the
Messenger class will be instantiated only once. The
getInstance method will fetch the static messenger instance once it is called.
Obviously, the previous approach has its pros and cons. We don’t have to worry about thread safety, and the instance will be created only when the
Messenger class will be loaded. However, it lacks flexibility. Let’s consider the scenario of passing configuration variables to the
Messenger constructor. You will find that it is not possible using the previous approach.
A workaround is to instantiate the
Messenger class on the
getInstance method.
package com.gkatzioura.design.creational.singleton.lait; public class Messenger { private static Messenger messenger; private Messenger() {} public static Messenger getInstance() { if(messenger==null) { messenger = new Messenger(); } return messenger; } public void send(String message) { } }
The above approach might work in certain cases, but it misses thread safety in cases where the class might get instantiated in a multithreaded environment.
The easiest approach to make our class thread-safe is to synchronize the
getInstance method.
package com.gkatzioura.design.creational.singleton.lait; public class Messenger { private static Messenger messenger; private Messenger() {} public synchronized static Messenger getInstance() { if(messenger==null) { messenger = new Messenger(); } return messenger; } public void send(String message) { } }
That one will work. At least the creation of the messenger will be synchronized and no duplicates will be created. The problem with this approach is that the synchronization is only needed once when the object is created. Using the above code will lead to unnecessary overhead.
The other approach is to use the Double-Checked Locking approach. Now, Double-Checked locking needs extra care since it is easy to pick the broken implementation over the correct one. The best approach is to implement lazy loading using the volatile keyword.
package com.gkatzioura.design.creational.singleton.dcl; public class Messenger { private static final Object lock = new Object(); private static volatile Messenger messenger; private Messenger() {} public static Messenger getInstance() { if(messenger==null) { synchronized (lock) { if(messenger==null) { messenger = new Messenger(); } } } return messenger; } public void send(String message) { } }
By using the volatile keyword, we prevent the write of a volatile to be reordered with respect to any previous read or write and a read of a volatile to be reordered with respect to any following read or write. Also, a mutex object is used to achieve synchronization.
To sum it all up, we created an object and we also made sure that there will be only one instance of that object. We made sure that there won’t be any problems instantiating the object in a multi-threaded environment.
You can find the source code on GitHub.
The abstract factory pattern is a creational pattern that is one of the most popular patterns, along with the builder and the factory pattern. Creational patterns are used to create objects without directly creating objects with a constructor.
The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes. The intent successfully.
So, let’s get into action and start solving problems!
Supposing we are responsible for the canning process of various products, there are two objects that have to be created: the can’s main body and the can’s top. Also, considering the fact that we might have various forms of canning, we might as well have various factories that can handle the canning process. For example, we might have a factory for beer canning or a factory for food canning.
In regards to the description above, it seems that abstract factory is the way to go. We do have a family of objects that that will provide the methods to create those objects.
package com.gkatzioura.design.creational.abstractfactory; public abstract class CanningFactory { public abstract CanTop createTop(); public abstract CanBody createBody(); }
As mentioned above, was using the abstract factory pattern in order to create a family of objects regarding the canning process. We insulated the creation process from the usage of the CanTop and CanBody. Also, we were able to create a family of objects without depending on their concrete classes.
You can find the source code at GitHub.
SOLID are a set of principles formulated by Robert C.Martin that are meant to guide developers to design and implement software that is easily maintainable, clear, and scalable. In other words, following these principles helps us to write a more solid software. These five principles are:
In this article, I want to focus on the second one: The Open/Closed Principle.
I highly doubt that there are too many software projects that don’t suffer any changes from the time they were designed. Software design is not a straightforward process. This is just a utopian thought in this industry. Any project will suffer some changes, especially in an agile environment. And even if the project is not developed in an agile environment, to design it perfectly from the beginning is almost impossible. At any time, we might need to add new things or have modifications to do, and if the existing components are not open for extension, then any change would imply a big risk.
One of our responsibilities as software developers is to anticipate what could change in what we write. We must focus to find the right abstraction level and the right point of behavior extension. We should not close our code to future extension and tie it to the current behavior because the behavior could always change and evolve. We should anticipate what could change and what could be extended. This does not sound too pragmatic, as this principle doesn’t tell us how to do that, but this doesn’t mean that there aren’t some good practices for respecting the principle.
So keep in mind when you write a software component to make it open to extension.
If the scope of this principle is to grow the application’s maintainability, why should the components be closed for modification? Every software entity should know how to do what it is designed to do and to do it well. For example, the Collections.sort method knows how to sort everything that implements the Comparable interface. This method is not limited to sorting just integers or just strings — it is not limited to any specific type. If you have a collection of objects that implement the Comparable interface, then you can sort it using the Collections.sort method. The sorting algorithm will work as it was designed, so we can say that it is closed to modification, but the sorting criteria will vary depending on the compareTo method implementation
The implementation of any software entity should be closed for modification. If the behavior changes, we should not change how a specific entity works, we just need to extend it. Just think of the enormous number of software applications that depend on the sort method. It is tested in the real application, it works good, and it is optimal. So if we need to sort a list of another type, should we change the sort method? Of course not!
So its implementation is closed to modification. This is how any software entity should be. But the key point is to let it be open to extension.
The OCP is just a principle and not a generic solution. It describes what your entities should respect, but it does not provide a specific solution. The good guys that designed the sort method let it be open to extension by using a Comparable interface. The method sorts a list of Comparable objects and uses the compareTo method as a sorting criterion. But this is just an example. There isn’t a single way of respecting this principle. However, there are some good general patterns that help us to achieve this.
For example, if the parameter types of a method are concrete classes, then the method is tightly coupled to those classes. It can’t receive anything else, except instances of that specific type. In this case, the method is not easily open to extension.
Any method should be simple. It should use a single level of abstraction and should do just one thing. If it respects this, then I’m pretty sure it doesn’t need to call all the parameters’ objects methods. In this case, should the method declare a concrete class as a parameter type? No.
You could create an interface that the class implements and set it as the parameter type — exactly as the Collections.sort method. This way, you can use that method with any class that implements that specific interface. It will work the same. It will call the parameters’ methods in the same way, but the behavior could be changed just by sending, as parameters, different implementations without changing the method.
Sure, you can extend that class and send, as parameters, instances of the child class, but since you cannot extend more than one class, it is more flexible (and clear) to just use interfaces.
The strategy pattern is a perfect example for programming by interface, not by implementation.
A design pattern is a general repeatable solution to a commonly occurring problem. Like someone says here, the design pattern is a cure against diseases, and the diseases, in our case, are violations of SOLID principles. Design patterns are not the only cure, but they are an efficient one. Even if it is not the only design pattern that accomplishes the OCP, one specific pattern seems to be, by definition, extremely fit for this purpose, and that is the strategy pattern. Via the strategy pattern, you encapsulate some specific strategies and select which one to use at runtime according to some criteria. So, by definition, using this pattern makes your code open to extension.
Like I said before, programming by interface and not by implementation is a best practice that we can use to design and implement code open to extension. Also, programming by interface is the key factor of the strategy pattern. It is a behavioral pattern, and, proven by the industry, one of the most useful design patterns. The principle is very simple: Encapsulate the strategies and decide what to use depending on some specific conditions. Following the strategy pattern, the behavior is decoupled by the classes that use it. You can switch between strategies without any class change.
The principle is very simple. All the strategy classes must implement a specific strategy interface. The class that uses the strategies, called the context class, is not bound to those specific strategy classes, but it is tied to the strategy interface. The context class encapsulates a strategy that could be injected in multiple ways (using Dependency Injection or the factory pattern or using a simple if condition — see this article for an introduction to Dependency Injection). So this mechanism is open to extension by giving you a way to use different strategies. Meanwhile, it is closed to modification, as the class that uses a strategy does not have to be changed no matter what the strategy is encapsulating.
Let’s see a simple example to better understand it. We will need a strategy interface, a class that uses the strategies, the context class, and some implementation of the strategy interface.
The context class should know just one thing about the strategies — what methods to call. This is what all the strategies have in common, so we will have a strategy interface with just the common methods (in our case, just one method).
public interface Strategy { public void doSomething(); }
And a context class that encapsulates a strategy implementation and executes it.
public class Context() { private Strategy strategy; // we set the strategy in the constructor public Context(Strategy strategy) { this.strategy = strategy; } public void executeTheStrategy() { this.strategy.doSomething(); } }
And let’s create two implementations for the Strategy interface.
public class Strategy1 implements Strategy { public void doSomething() { System.out.println(“Execute strategy 1”); } } public class Strategy2 implements Strategy { public void doSomething() { System.out.println(“Execute strategy 2”); } }
Now we can bind this together. The idea is to send to the context class the strategy we want to run. Like I said before, you can use Dependency Injection or the factory pattern for this, but it’s out of this article’s scope, so let’s just make a simple Demo class to see how it works.
public class Demo() { public static void main(String[] args) { Context context = new Context(new Strategy1()); // we inject the Strategy1 context.executeTheStrategy(); // it will print “Execute strategy 1”; context = new Context(new Strategy2()); // we inject the Strategy2 context.executeTheStrategy(); // it will print “Execute strategy 2” } }
So the context is decoupled from a specific strategy class. You could implement however many strategies you want and no matter how they work and what you want them to do, you don’t need to modify the context class. The context class knows just that it must call doSomething method and it is enough.
This is a trivial example, but the possibilities are unlimited. Just think of the advantages you get here, and it is not hard at all to follow this simple pattern. Just use interfaces and let a concrete class to know just what it needs to know about something by tying it to an interface instead to a concrete class. This way, you can extend the behavior just by implementing different strategies and without changing the context class’s functionality.
When you want to write code that follows the OCP, you should not limit yourself just on the strategy pattern or to “program by interface, not by implementation.” By using these best practices, I just wanted to show the power of having something open to extension and closed to modification.
Like I said before, not following this principle is like a disease, but design patterns aren’t the only cure. Strive to find the right abstraction levels and don’t use more than one single level of abstraction in a method. Find the pointcut between those levels, separate the concerns, and see how you can extend the functionality without changing the context classes. And don’t forget to look at the other SOLID principles.:
<-, they know to pay special attention, as it is a stateful function
=,
Statedata type to write functions that need state
Writerdata type to log state transitions