What are strategies in java with examples

Lulu 15 Published: 02/11/2025

What are strategies in java with examples

I'm happy to help you with that!

Java is an object-oriented programming language known for its platform independence and versatility. Here, we'll dive into some of the most effective strategies used in Java, along with examples:

Single Responsibility Principle (SRP): Each class should have a single responsibility and not be overly complex.

Example:

// Bad implementation

public class Employee {

public void updateName(String name) {

this.name = name;

}

public void calculateSalary() {

// calculation logic

}

}

// Good implementation

public interface UpdateName {

void setName(String name);

}

public interface CalculateSalary {

int calculate();

}

public class Employee implements UpdateName, CalculateSalary {

private String name;

@Override

public void setName(String name) {

this.name = name;

}

@Override

public int calculate() {

// calculation logic

}

}

Don't Repeat Yourself (DRY): Avoid duplicating code by extracting reusable blocks into separate methods or classes.

Example:

// Duplicate code

public class BankAccount {

public void debit(int amount) {

System.out.println("Debiting " + amount);

}

public void credit(int amount) {

System.out.println("Crediting " + amount);

}

}

// Improved implementation using DRY principle

public abstract class Transaction {

public abstract void processTransaction(int amount);

}

public class Debit extends Transaction {

@Override

public void processTransaction(int amount) {

System.out.println("Debiting " + amount);

}

}

public class Credit extends Transaction {

@Override

public void processTransaction(int amount) {

System.out.println("Crediting " + amount);

}

}

Encapsulation: Hide internal implementation details and expose only necessary information through a controlled interface.

Example:

// Poor encapsulation

public class Person {

private String name;

public void setName(String name) {

this.name = name;

}

public String getName() {

return name;

}

}

// Improved encapsulation using access modifiers

public class Person {

private final String name; // Immutable

public Person(String name) {

this.name = name;

}

public String getName() {

return name;

}

}

Composition: Combine objects to form a new, more complex object that exhibits specific behaviors.

Example:

// Simple implementation

public class Car {

private Engine engine;

public void startEngine() {

engine.start();

}

}

public class Truck extends Car {

// ...

}

// Composition example

public interface Engine {

void start();

}

public class GasolineEngine implements Engine {

@Override

public void start() {

System.out.println("Gasoline engine started");

}

}

public class ElectricEngine implements Engine {

@Override

public void start() {

System.out.println("Electric engine started");

}

}

public class Car {

private final Engine engine;

public Car(Engine engine) {

this.engine = engine;

}

public void startEngine() {

engine.start();

}

}

Factory Method: Provide a way to create objects without specifying the exact class type.

Example:

// Simple implementation

public abstract class Vehicle {

public abstract void drive();

}

public class Car extends Vehicle {

@Override

public void drive() {

System.out.println("Driving a car");

}

}

public class Truck extends Vehicle {

@Override

public void drive() {

System.out.println("Driving a truck");

}

}

// Factory method example

public interface VehicleFactory {

Vehicle createVehicle();

}

public class CarFactory implements VehicleFactory {

@Override

public Vehicle createVehicle() {

return new Car();

}

}

public class TruckFactory implements VehicleFactory {

@Override

public Vehicle createVehicle() {

return new Truck();

}

}

These strategies can help you write more maintainable, flexible, and scalable code in Java. Remember to apply these principles judiciously, as over-engineering can be detrimental to the overall system performance.

What is the Strategy pattern in Java 8?

The Strategy pattern is a behavioral design pattern that defines a family of algorithms, encapsulates each one as an object, and makes them interchangeable. This approach allows objects with varying behaviors to work together seamlessly.

In Java 8, the Strategy pattern can be implemented using interfaces and lambda expressions. Here's an example:

// Strategy interface

interface SortingStrategy {

List sort(List list);

}

// Concrete strategy classes implementing the interface

class SortByName implements SortingStrategy {

@Override

public List sort(List list) {

list.sort((a, b) -> a.compareTo(b));

return list;

}

}

class SortByLength implements SortingStrategy {

@Override

public List sort(List list) {

list.sort((a, b) -> a.length() - b.length());

return list;

}

}

// Context class using the strategy interface

class ListProcessor {

private SortingStrategy sortingStrategy;

public ListProcessor(SortingStrategy strategy) {

this.sortingStrategy = strategy;

}

public void processList(List list) {

list = sortingStrategy.sort(list);

System.out.println("Sorted list: " + list);

}

}

// Client code

public class Main {

public static void main(String[] args) {

ListProcessor processor = new ListProcessor(new SortByName());

List list1 = Arrays.asList("banana", "apple", "orange");

processor.processList(list1);

processor = new ListProcessor(new SortByLength());

List list2 = Arrays.asList("hello", "world", "java8");

processor.processList(list2);

}

}

In this example:

The SortingStrategy interface defines the algorithm's behavior (i.e., sorting). Concrete strategy classes (SortByName and SortByLength) implement the interface, providing different sorting algorithms. The ListProcessor class uses the strategy interface to process lists. It can be instantiated with different strategies for different sorting needs.

In Java 8, lambda expressions make it easier to implement the Strategy pattern without creating explicit concrete strategy classes. For example:

// Simplified version using lambda expressions

public class Main {

public static void main(String[] args) {

List list = Arrays.asList("banana", "apple", "orange");

SortingStrategy sortingStrategy = (a, b) -> a.compareTo(b);

processor.processList(list);

sortingStrategy = (a, b) -> a.length() - b.length();

processor.processList(list2);

}

}

By using lambda expressions to implement the strategy interface, you can create anonymous concrete strategies without explicitly declaring classes. This approach is particularly useful for small, simple algorithms.

In conclusion, the Strategy pattern in Java 8 allows for flexible and reusable algorithm implementations by encapsulating different behaviors within objects. This design pattern enables easy extension of functionality while maintaining loose coupling between components.