Q:

When to use (decorate with) what and why - DefaultErpHttpDestination, DefaultHttpDestination?

Using java SAP Cloud SDK
I have to use com.sap.cloud.sdk.s4hana.datamodel.odata.namespaces.outbounddeliveryv2.batch.OutboundDeliveryV2ServiceBatch.execute(HttpDestinationProperties destination) to perform some updates on S/4 system. This method, execute takes an argument of type HttpDestinationProperties.
Since I need a destination, I am using below code to get destination:
HttpDestination destination = DestinationAccessor.getDestination("MyErpSystem").asHttp();

Since HttpDestination extends HttpDestinationProperties, we can safely pass it to execute. But according to step 4 of 'Connect to OData Service on Cloud Foundry Using SAP Cloud SDK' tutorial, the code for accessing destination looks like this:
ErpHttpDestination destination = DestinationAccessor.getDestination("MyErpSystem").asHttp().decorate(DefaultErpHttpDestination::new);

and then they pass that destintion to the execute method of the service.
My question is that since execute methods takes an argument of type HttpDestinationProperties, How would I know that I have to use DefaultErpHttpDestination? Same thing goes for DefaultHttpDestination.
I have following questions - 

When and why should I wrap the destination in DefaultErpHttpDestination?
When and why should I wrap the destination in DefaultHttpDestination?
Why should I wrap the destination in above two wrappers at all?

A:

This is an excellent question!
The context:

Of course you can keep using your original approach:

HttpDestination destination =
  DestinationAccessor.getDestination("MyErpSystem").asHttp();

This is the recommended way for destinations targeting a generic HTTP service endpoint.
It loads the required destination properties for HTTP connections, e.g. URL, Authentication, ...

In the tutorials we are describing the integration with S/4HANA OData services:

HttpDestination destination =
  DestinationAccessor.getDestination("MyErpSystem").asHttp()
    .decorate(DefaultErpHttpDestination::new);

By "decorating" the HttpDestination instance with ERP properties, we enable additional S/4 related HTTP request headers: sap-client and sap-locale. With the above configuration, those values are read automatically from the destination service - if they are set.

Your questions (changed order):

"When and why should I wrap the destination in DefaultHttpDestination?"

DestinationAccessor#getDestination returns a generic Destination. In order to make sure we are dealing with HTTP (and not RFC) connections, you need to run #asHttp - as you already do. With the resulting HttpDestination instance, you can run HTTP queries like OData and REST. Depending on your use case, no additional wrapping is required.
For example, if you were about to use BAPI endpoints, then you'd need to run #asRfc instead. This method will check for different destination properties to make sure all required values are set.

"When and why should I wrap the destination in DefaultErpHttpDestination?"

It is recommended to wrap the destination in DefaultErpHttpDestination only when you are dealing with S/4 service endpoints and you rely on custom values for sap-client and sap-locale. The wrapping can be done at any time of your application runtime, as long as it happens before #execute(HttpDestinationProperties) method.
If you do not want to wrap it a second time, then you'd need to manually manage the HTTP request headers for sap-client and sap-locale.

"Why should I wrap the destination in above two wrappers at all?"

This is the API contract. It makes sure all required destination properties are correctly set before even invoking the actual request. The (optional) ERP flavored wrapping of the destination instance was provided to make sure all S/4 properties are automatically considered as well.

