Design pattern to force client of a class to call a method

by BornToCode   Last Updated December 10, 2017 18:05 PM

I have a large class with complex properties. I'd like to introduce a default implementation, allow the user to override part of the default implementation and also make sure the user calls a sync method so that the object is always at a consistent state.

public class Complex {
    public int Id { get; set; }
    public CustomComplex1 Custom1 { get; set; }
    public CustomComplex2 Custom2 { get; set; }

    public Complex()
    {
        Custom1 = new CustomComplex1() { Name = "Bla", Cost = 55, etc..} // provide default values
    }

    //this method must always be called!
    public void RegisterObject()
    {

    }     

}

Class could be used like this:

  var a = new Complex(); // all default values set
  a.Custom1.Name = "newName"; // I'd like to use the default values, but just change something..
  a.RegisterObject(); // problem - client might forget to call this! 

I thought about using the builder pattern, but then I'll have to provide methods to modify each variation of CustomComplex1 type - too much work & maintenance. From the other hand if I expose Custom1 as a public property it looks like I'm doing the exact opposite of the builder pattern's intent. So what is a good way to A.allow the user modify any property of my complex object and B.force him to call the RegisterObject on compile time?



Answers 2


You can use builder pattern. The "WithX" stuff is not really main purpose of builder and is just syntax sugar to make some usage simpler.

Your code, using builder, could very well look like this :

var build = new ComplexBuilder(); // all default values set
build.Custom1.Name = "newName";
Complex a = build.Build(); // register inside here

This is valid and normal builder pattern.

Euphoric
Euphoric
December 10, 2017 17:35 PM

If you don't want to use builder pattern, and you want to get fancy, you could use setting-changing delegate. I saw something similar in configuration of ASP.NET Core.

public class Complex {
    public int Id { get; set; }
    public CustomComplex1 Custom1 { get; set; }
    public CustomComplex2 Custom2 { get; set; }

    public Complex(Action<CustomComplex1, CustomComplex2> configure)
    {
        Custom1 = new CustomComplex1() { Name = "Bla", Cost = 55, etc..} // provide default values
        configure(Custom1, Custom2);
        RegisterObject();
    }

    private void RegisterObject()
    {

    }
}

The caller can then pass the delegate that changes the Custom objects.

And if you don't like doing this in a constructor, make a static Create method, make the constructor private and just call the delegate and RegisterObject from there.

Euphoric
Euphoric
December 10, 2017 17:40 PM

Related Questions





Design help needed

Updated March 29, 2017 12:05 PM