MVC pattern is useful to build the UI (be it CLI, GUI, web page, REST API or something totally different). For integration purposes, you'll want to use other patterns, for instance Facade.
Let's say you're building an ice cream machine. You have a platform interface:
package com.plaform.icecream;
public interface IceCreamMachine {
public void measureCream(int milliLiters);
public void measureCondensedMilk(int milliLiters);
public void measureVanillaExtract(int tableSpoons);
public void measureCacaoPowder(int tableSpoons);
public void mixIngredients();
public void freezeConcoction();
public Object handOverExperimentResults();
}
Then you have your model class of MVC:
package com.cli.icecream.model;
public class Icecream {
private int amount;
private Flavour flavour;
// getters, setters, toString, etc.
}
Flavours as enum:
package com.cli.icecream.model.values;
public enum Flavour {
VANILLA, CHOCOLATE;
}
Controller:
package com.cli.icecream.controller;
public class IceCreamController {
private IceCreamFacade serviceFacade;
public IceCreamController(IceCreamFacade serviceFacade) {
this.serviceFacade = serviceFacade;
}
public void handleShowingFlavours() {
// ...
}
public IceCream handleOrderingIcecream(int balls, Flavour flavour) {
// validations, etc.
return serviceFacade.getIceCream(balls, flavour);
}
}
Now the way to hide the actual details behind the product from the MVC, you can create a Facade that will integrate the two:
package com.cli.icecream.integration;
public interface IceCreamFacade {
public IceCream getIceCream(int balls, Flavour flavour);
}
and:
package com.cli.icecream.integration;
public class IceCreamFacadeImpl {
private IceCreamMachine iceCreamMachine;
public IceCreaFacadeImpl(IceCreamMachine iceCreamMachine) {
this.iceCreamMachine = iceCreamMachine;
}
public IceCream getIceCream(int balls, Flavour flavour) {
int creamMl = ConversionUtil.calculateAmountOfCream(balls);
int condensedMilkMl = ConversionUtil.calculateAmountOfCondensedMilk(balls);
int flavourSubstanceTbsp = ConversionUtil.calculateAmountOfFlavourSubstance(balls);
iceCreamMachine.measureCream(creamMl);
iceCreamMachine.measureCondensedMilk(condensedMilkMl);
switch (flavour) {
case VANILLA:
iceCreamMachine.measureVanillaExtract(flavourSubstanceTbsp);
break;
case CHOCOLATE:
iceCreamMachine.measureCacaoPowder(flavourSubstanceTbsp);
break;
}
mixIngredients();
freezeConcoction();
Object results = iceCreamMachine.handOverExperimentResults();
return ConversionUtil.convertResultsToIceCream(results);
}
}
This way the UI (MVC) consist of classes that are blissfully unaware of how the integrated platform works and vice versa, i.e. decoupled. As an added benefit, if either component changes its behaviour, all your logic to integrate the two are in one place, instead of splattered all over either application.