Pattern for a function that must be called in first, followed by client code, then a function that must be called last?

StackOverflow https://stackoverflow.com/questions/19649590

  •  01-07-2022
  •  | 
  •  

Question

Similar to the Builder pattern where a series of functions or code that must be called in a specific order can be called from one public function.

Is there a pattern for when the client must call a specific initializer function first, followed by zero or more client code calls, followed by a deinitializer function last?

I'd like to make it so the client doesn't have to worry about calling (or forgetting to call) the init and deinit functions and can just worry about their own code.

Was it helpful?

Solution

Depending on language used, you can try with NVI idiom or Proxy pattern. There are also some other idioms/patterns tackling with this problem indirectly.

OTHER TIPS

My preference in this situation is to have the client call a single function (which we might call executeFn()), with the parameters f, which is a function that the client provides, and fp which is a way for the the client to provide arguments to f() via executeFn(). f() may also be required to accept arguments provided by executeFn(), which have been created in the initialisation step, and to return a value that is used by executeFn() in the de-initialisation step.

In Python, for instance:

def executeFn (f, fp):
    # do the initalisation here
    i = len(fp)
    f(fp,i)
    # do the de-initalisation here

def myFn (p,i):
    print (i)
    print (p)

executeFn(myFn,"message")

... which outputs:

7
message

Addition to Simon's answer, you can do delegation instead of hard-coding the operation inside, and depended on language, you can using delegation to be passed.

For example in C# for calling a webservice, which language is able to pass delegation:

public class Invoker{
    public ResultClass Invoke(Func<InvokeResultClass, ServiceClass> action){
        ResultClass result;
        using(ServiceClass svc = new ServiceClass()){ //create the service
            InvokeResultClass invokeResult = action(svc);
            // do something with InvokeResultClass and creating ResultClass
        } // dispose it
        return result;
    }
}

The consumer:

Invoker inv = new Invoker();
ResultClass result = inv.Invoke( svc => svc.CallWebServiceMethod(param1, param2, etc) );

You may need the Adapter Pattern where you have the client call methodA() on adapter which implementation is

class Adaptee
{
    methodA()
    {
        // some code
    }
}
class Adapter extends Adaptee
{
    methodA()
    {
        mustBeCalledFirst(); //methodB()
        super.methodA(); //from adaptee
        mustBeCalledLast(); //methodC()
    }
}
class Client
{
    Adapter adapter;
    methodA()
    {
        adapter.methodA();
    }
}

EDIT

If your methodB() and methodC() is in your client you may add a client interface

class Adaptee
{
    methodA()
    {
        // some code
    }
}
class Adapter extends Adaptee
{
    ClientInterface clientInterface;
    public Adapter( ClientInterface clientInterface)
    {
         this.clientInterface = clientInterface ;
    }
    methodA()
    {
        clientInterface.methodB()
        super.methodA(); //from adaptee
        clientInterface.methodC()
    }
}
class Client implements ClientInterface
{
    Adapter adapter;
    methodA()
    {
        adapter.methodA();
    }
    @override
    methodB(){}
    @override
    methodC(){}
}
Interface ClientInterface
{
     methodB();
     methodC();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top