Customizer Pattern

Motivation Usually classes that require huge overhead while initialization are cached. This comes with a problem that we can not store client specific information into the class since that class's instance is shared between multiple threads.

Example Suppose there is an interface Html_Maker. And suppose Table_Maker extends from it. Table_Maker has time consuming operation makeHtml(). Since it's time consuming, client classes cache Table_Maker to save time.

  public interface Html_Maker {
    public void setBorder(String border);
    public void setStyle(String cssStyle);
    public void make(Writer writer);
  }
  public class Table_Maker implements Html_Maker {
    String border = "";
    String style = "";
    public void setStyle(String style){this.style=style;}
    public void setBorder(String border){this.border=border;}
    public void make(Writer writer){
      writer.write(makeHtml());
    }
  }

As you can see, the problem with this approach is that we have to create instance of Table_Maker every time we need to make the table just because the style and border for the tables might be different for different tables and hence we will not be able to cache the Html_Maker. We can over come this problem by passing the border and style as parameters to the table in the method make(). But this poses a problem that if we want to add one more variant, we end up changing the interface. To overcome this problem, we can have a class Customizer.

  public interface Customizer {
    private String style;
    private String border;

public String getStyle(){return style;} public String getBorder(){return border;}

public String setStyle(String style){this.style=style;} public String setBorder(String border){this.border=border;} }

The client will set up the Customizer and then pass it to Table_Maker. This is the result..

  public class Table_Maker implements Html_Maker {
    public void make(Writer writer, Customizer cust){
      writer.write(makeHtml(cust));
    }
  }

Thus the client classes can cache the Table_Maker and then pass the Customizer to customize Table_Maker whenever needed.

I do not know if the same pattern exists elsewhere. If it's found, please attach a link to that page from here. --VhIndukumar

is this not the pattern of css itself? If you look at html elements as being 'wrapped' by a css decorator you'll see exactly this pattern, in the sense that all styling is stored in a separate stylesheet and is not part of the table.


Compare and contrast with Decorator?


I think decorator encloses the target object and then extends the target object's behaviour. Decorator does not change the behaviour of the target. The above pattern does not extend but change the behaviour of the target. Also, it customizes the object for a method invocation and not for the life time of the object. - Indukumar


Alternate idiom (not being suggested as sensible, just as another alternative) - combine CopyOnWrite and flyweight. Make all Table_Maker objects immutable. setMethods() are no longer void, but return Table_Maker objects. These are clones of the prototype you tried to change, with one piece changed. The clones are not created on demand but are flyweights. This gives you a small number of styled tables instead of lots of instances.


This looks exactly the same as a parameter block, but with the parameters held in a class instead of the more traditional struct. It is a very heavily used technique in my experience - not just to improve maintainability but also to improve performance and readability. The performance benefit results when a function (or several similar functions) is likely to be called repeatedly with similar parameters. Setting up the parameters for each call on the stack has a high overhead compared with setting up a class or struct once then putting a pointer on the stack for each call. The readability benefit is that it also reduces the amount of redundant repetition obscuring the logic of your source code - you don't have to keep repeating long parameter lists. In fact, a class is a parameter block (the parameter block pointer being passed using the implicit 'this' pointer for each method) - but using additional classes to provide additional parameter blocks is still a useful technique. Also, the Customizer class can usefully have several setup functions to set its various parameters and do some basic checking - simplifying the stages for setting up the parameter block and ensuring the main classes method then receives a validated set of parameters, potentially leaving less work for it to do.

Hence...

  class c_Main;
  class c_Customizer;

...

c_Main l_Main; c_Customizer l_Customizer;

l_Customizer.Setup_Fn_1 (various_pars); l_Customizer.Setup_Fn_2 (various_pars); l_Customizer.Setup_Fn_3 (various_pars);

if (l_Customizer.OK ()) l_Main.Main_Call (l_Customizer);

// Only change a few parameters... l_Customizer.Setup_Fn_3 (various_pars);

if (l_Customizer.OK ()) l_Main.Main_Call (l_Customizer);


CategoryCoding


EditText of this page (last edited November 21, 2014) or FindPage with title or text search