Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforce method execution order in Abstract Class

I have a business case in which 3 things need to happen, in sequence:

  1. download()
  2. process()
  3. upload()

Now, the Abstract Class FileTransfer provides implementation for 1. downloadFiles() and 3. upload(), but not 2. process() -- child classes (like MusicFileTransfer or VideoFileTransfer or PDFFileTransfer) will do different things in the 2. process() stage.

So it seems clear to make the abstract class like so:

public abstract class FileTransfer {

public void download() {
    // implementation provided
}

public abstract void process(); // implementation not provided

public void upload() {
    // implementation provided
}

}

But one issue -- There will never ever be a time in which it is okay for, say, MusicFileTransfer to call process() before download() or any other order. The process must always be 1. download(), 2. process(), then 3. upload().

So I imagine something like:

public void doTransfer() {
    // private methods since we want to enforce this order of execution
    download(); // implem provided
    process(); // abstract method
    upload(); // implem provided
}

in FileTransfer to wrap around these three calls. But in order for the child class MusicFileTransfer to override process() ... it must be public or protected (not private).

What should I do to work around this pickle? Have a public doTransfer() and a public process() and just make sure process() is never ever called? Or do away with the doTransfer() and hope that the order is always correct?

like image 280
Don Cheadle Avatar asked Mar 29 '26 23:03

Don Cheadle


2 Answers

You need the template method pattern. Create a doTransfer method (final) in the FileTransfer class that defines the order of the methods that needs to be called. Make the download and upload methods also final so they can't be overridden. The process method is the abstract method; make it protected so it can't be called from other classes. It can't be public, or else it can be called by some other class out of order.

public final void doTransfer() {
    // protected methods since we want to enforce this order of execution
    download(); // implem provided
    process(); // abstract method
    upload(); // implem provided
}
protected final void download() {
    // implementation provided
}

protected abstract void process(); // implementation not provided

protected final void upload() {
    // implementation provided
}

Then subclasses can only implement the process method and they can't override any other methods.

like image 61
rgettman Avatar answered Apr 01 '26 13:04

rgettman


In this case you might consider making the process() method protected, meaning that subclasses can extend it, but consumers may not call it directly. Additionally, perhaps download() and upload() methods shouldn't be public either. Consider the the following:

public abstract class FileTransfer {

    private void download() {
        // implementation provided
    }

    protected abstract void process(); // implementation not provided

    private void upload() {
        // implementation provided
    }

    public void doTransfer() {
        // private methods since we want to enforce this order of execution
        download(); // implem provided
        process(); // abstract method
        upload(); // implem provided
    }

}

Sample implementation class:

public class FTPFileTransfer {

    protected void process() {
        // implement FTP file transfer here

    }
}

Sample consumer method:

public void consumerMethod() {
    FileTransfer fileTransfer = factory.getFTPFileTransfer();
    fileTransfer.doTransfer();
} 
like image 43
cogitos Avatar answered Apr 01 '26 13:04

cogitos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!