Decorator-Placeholder pattern …

I had a dilemma … first let me explain the structure I have.
Class Page is the fulcrum of a hierarchy, which is then inherited to create tests. Every Page process Elements.

The goal is somehow in any Test to be able to write code that can be executed Before or After processing an element !!

The twist is that another programmer can create different Page class to support a new type of test. But I have to preserve this capability across all cases.

Here is the hierarchy :

  • ProtoPage
    • Page
      • TestPage
      • TestPage2
    • PageType2
      • TestPageType2
    • PageType3
  • Elements

First I tried to use Callbacks, but soon abandoned the idea. Then I thought about using Reflection, but still too complicated. Then it hit me ! The solution was staring me in the face.

I could simply put the before_element() and after_element() in the Page class and allow Elements to use them. That will work but then I have to communicate with the other programmers to keep the methods in their versions of Page.
It was good thing that Page already inherit ProtoPage, so I put the methods there. Now they are always available.

The second step was to pass the page object when I create Elements, so that Elements can call the methods.
But I already had that for other reasons, so nothing to do here.

And that’s it, problem solved !! Before&After methods go in ProtoPage and Elements can access them via the page object.

Below is a sketch of the code.

If you are wondering why before&after are not Abstract methods, the reason is they are not required but are optional. They are PLACEHOLDER methods, so I’m calling this placeholder pattern.

the code

public class ProtoPage {
  //placeholders
  public void before_element() {};
  public void after_element() {};
  
}

public class Page extends ProtoPage {
  
  public void process() {
    Elements es = new Elements(this);
    es.process();
  }
}

public class Elements {
  
  public ProtoPage page;
  
  Elements(Page page) {
    this.page = page;
  }
  
  public String[] all() {
    return new String[] {"el1", "el2", "el3" };
  }
  
  public void process() {
    for (String el : this.all()) {
    page.before_element();
    System.out.println("> process elements : " + el);
    page.after_element();
    }
  }
  
}

public class TestPage extends Page {
  @Override
  public void before_element() {
    System.out.println("> before element ...");
  };
  @Override
  public void after_element() {
      System.out.println("> after element ...");
  };
  
}
public class Test {
public static void 
         main(String[] args) {

 System.out.println("Hello World!");

 TestPage tp = new TestPage();
 tp.process();

 }
}
Hello World!
> before element ...
> process elements : el1
> after element ...
> before element ...
> process elements : el2
> after element ...
> before element ...
> process elements : el3
> after element ...