Composing functionality of sealed class with interfaces

Posted on

Problem

public sealed class Client
{
    private Simulation _simulation;
    public Client(ITickProvider tickProvider, ICommandReceiver commandReceiver)
    {
        _simulation = new Simulation();
       tickProvider.Tick += HandleTick;
       commandReceiver.CommandReceived += HandleCommandReceived;
    }
    private void HandleTick ()
    {
        //Distribute tick to _simulation
    }
    private void HandleCommandReceived(Command command)
    {
        //Inject command to _simulation
    }
}

Client operates a multithreaded Simulation, distributing ticks and external input to the Simulation.

ITickProvider provides a Tick event that runs every e.g. fixed interval, button click, etc..

ICommandReceiver receives external input (Commands); i.e. User input, server input, serialized input, etc..

Because the interfaces’ implementations are usually exclusive, I decided to make Client sealed and inject the functionality with the constructor. This also helps with controlling thread-sensitive access to Simulation.

What is the pattern of composing a sealed class with modular interfaces? Is this a well-known pattern and if so, have I implemented it correctly?

Solution

It depends on the actual class requirements along with the overall code factors.
For instance,

  • Do you think that Client class can be extended in the future? (not by inheritance surely since it’s sealed).
  • How often this class is going to be called?
  • How simple you need to simplify the initiation of this class? (as a way to automate handling of its dependencies)
  • Are these interfaces going to be recalled or extended in any other way except this class ?
  • Do interfaces have many unneeded members? (say you only need some members and not all of them).

You must investigate that, and decide the best approach that would be feasible to your current project.

As kick-starter that would give you some ideas after looking at your class, and interfaces, without knowing your actual implementations, I could say the safest way is to create ClientHandler and pass it to the constructor instead. something like this :

public class ClientHandler : ITickProvider, ICommandReceiver
{
    private readonly Simulation _simulation;
    public ClientHandler(Simulation simulation)
    {
        if(simulation == null)
        {
            throw new ArgumentNullExecption(nameof(simulation));
        }
        _simulation = simulation;
    }
    
    // ITickProvider implementation
    // Do the handeling here 
    public void Tick() { ... }

    // ICommandReceiver implementation
    // Do the handeling here 
    public void CommandReceived() { ... }
}

public sealed class Client
{
    private readonly ClientHandler _handler; 
    
    public Client(ClientHandler clientHandler)
    {
        if(clientHandler == null)
        {
            throw new ArgumentNullExecption(nameof(clientHandler));
        }
        
        _handler = clientHandler;           
    }
}

This is better, because you’ll have more room in your code to be able to control the handler and the client side-by-side, with a benefit of extending the handler as per requirement. Also, Implementing interfaces would ease your work, especially if your work includes Reflection. You can also keep the handler as abstract class and inherit it to have more customizable handlers.

Leave a Reply

Your email address will not be published. Required fields are marked *