Skip to main content

Design patterns - Strategy pattern with Java Example

What is Strategy Design pattern?

Strategy design pattern comes under behavioural design pattern. It is also known as Policy pattern. It defines a family of algorithms and encapsulates each algorithm. The algorithm can be interchanged without changing much code. It bury algorithm implementation details in derived classes. It favours composition over inheritance.

Derived classes could be implemented using the template design pattern (We will discuss about it later on).

Implementation

We will take example of Compressing files. For compressing files, we can either use zip or can use rar compression strategy. In Strategy Design pattern, we will have following classes and interface.

1. We will define our Strategy to compress files.

package com.gauravbytes.strategy.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public interface CompressionStrategy {
     //Compression algorithm
     public void compressFiles(List<File> files) throws FileNotFoundException;
}

2. We will now create two concrete classes which define the compression Strategy. i.e. ZIP and RAR strategy to compress files.

package com.gauravbytes.strategy.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;
public class ZipCompressionStrategy implements CompressionStrategy {
   @Override
    public void compressFiles(List<File> files) throws FileNotFoundException {
     //using ZIP approach

    }
}

package com.gauravbytes.strategy.client;
import java.io.File;
import java.util.List;
public class RarCompressionStrategy implements CompressionStrategy {
     @Override
     public void compressFiles(List<File> files) {
             //using RAR approach
    }
}

3. We need on context/utility which will actually interact with the actual strategies to get work done.

package com.gauravbytes.strategy.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class CompressionUtility {
     private CompressionStrategy strategy;
     
     //this can be set at runtime by the application preferences
     public void setCompressionStrategy(CompressionStrategy strategy) {
             this.strategy = strategy;
    } 

    public void createArchive(List<File> files) throws Exception, FileNotFoundException {
         if (files == null)
             throw new RuntimeException(new NullPointerException("ListFile is null"));

         strategy.compressFiles(files);
    }
}

4. Now, we require client which will use the context/utility and generate the compressed files
package strategy.client;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
          List<File> files = new ArrayList<File>();
          CompressionUtility fileCompressor = new CompressionUtility();
          boolean isZipTypeCompression = false;
          //we could assume context is already set by preferences
         CompressionStrategy strategy = isZipTypeCompression ? new ZipCompressionStrategy() : new RarCompressionStrategy();

        fileCompressor.setCompressionStrategy(strategy);
       //get a list of files
       try {
         fileCompressor.createArchive(files); 
       } 
       catch (Exception e) { }
   }
}

Important note

I would like to explain how composition is favoured in Strategy design pattern. In class CompressionUtility, we have reference to CompressionStrategy interface and in context/utility class, there is one setter method for compression strategy i.e. you can change the alogorithm at run-time in context class if required.

Comments

Popular posts from this blog

Data Analytics: Watching and Alerting on real-time changing data in Elasticsearch using Kibana and SentiNL

In the previous post , we have setup ELK stack and ran data analytics on application events and logs. In this post, we will discuss how you can watch real-time application events that are being persisted in the Elasticsearch index and raise alerts if condition for watcher is breached using SentiNL (Kibana plugin). Few examples of alerting for application events ( see previous posts ) are: Same user logged in from different IP addresses. Different users logged in from same IP address. PermissionFailures in last 15 minutes. Particular kind of exception in last 15 minutes/ hour/ day. Watching and alerting on Elasticsearch index in Kibana There are many plugins available for watching and alerting on Elasticsearch index in Kibana e.g. X-Pack , SentiNL . X-Pack is a paid extension provided by elastic.co which provides security, alerting, monitoring, reporting and graph capabilities. SentiNL is free extension provided by siren.io which provides alerting and reporting function

React Ecosystem: Building BlogPost application with React and React Hooks

Building a Blog Post application Let's create a blog post application. It will have below features: Option to search blog posts. Option to list blog posts. Option to show blog post. Create a new project with npx create-react-app react-blog-posts --template typescript . Create BlogPosts.tsx component under src/components folder and IBlogPost model under src/models . import React from 'react'; import IBlogPost from '../models/IBlogPost'; interface IBlogPostsProps { posts: Array<IBlogPost> } function BlogPosts(props: IBlogPostsProps) { return ( <div className="blog-container"> <ul className="blog-posts"> { props.posts.map(post => <li key={post.id}>{post.title}</li>) } </ul> </div> ); } export default BlogPosts; interface IBlogPost { id: number title: string content: string author: string postedOn: string tags: string[]

Java 8 - Lambda expressions

In this post, we will cover following topics. What are Lambda expressions? Syntax for Lambda expression. How to define no parameter Lambda expression? How to define single/ multi parameter Lambda expression? How to return value from Lambda expression? Accessing local variables in Lambda expression. Target typing in Lambda expression. What are Lambda expressions? Lambda expressions are the first step of Java towards functional programming. Lambda expressions enable us to treat functionality as method arguments, express instances of single-method classes more compactly. Syntax for Lambda expression Lambda has three parts: comma separated list of formal parameters enclosed in parenthesis. arrow token -> . and, body of expression (which may or may not return value). (param) -> { System.out.println(param); } Lambda expression can only be used where the type they are matched are functional interfaces . How to define no parameter Lambda expression? If the la