public class ObjectAdapterPattern {
    public static void main(String[] args) {
        Outlet chineseOutlet = new ChineseOutlet();
        Outlet americanOutlet = new AmericanOutlet();
        CellPhone phone = new CellPhone();

        phone.plugToOutlet(chineseOutlet);
        phone.charge();

        phone.unplugFromOutlet();

        phone.plugToOutlet(americanOutlet);
        phone.charge();
    }
}

/**
 * Existing interface
 */
abstract class Outlet {
    public abstract int getVoltage();
}

/**
 * Existing class (Adaptee) 1
 */
class ChineseOutlet extends Outlet {
    public int getVoltage() {
        return 220;
    }
}

/**
 * Existing class (Adaptee) 2
 */
class AmericanOutlet extends Outlet {
    public int getVoltage() {
        return 110;
    }
}

/**
 * Target interface
 */
interface OutletPlugable {
    public void getPowerFromOutlet();
}

/**
 * Adapter
 */
class PowerAdapter implements OutletPlugable {
    Outlet outlet;

    public PowerAdapter(Outlet outlet) {
        this.outlet = outlet;
    }

    public void getPowerFromOutlet() {
        int voltage = outlet.getVoltage();

        if (voltage < 100) {
            throw new RuntimeException("Voltage is too low!");
        } else if (voltage == 110) {
            System.out.println("Voltage is 110V, do nothing.");
        } else if (voltage <= 240) {
            System.out.println("Transforming voltage to 110V.");
        } else {
            throw new RuntimeException("Voltage is too high!");
        }
    }
}

/**
 * Client
 */
class CellPhone {
    OutletPlugable powerAdapter;

    public void plugToOutlet(Outlet outlet) {
        this.powerAdapter = new PowerAdapter(outlet);
        System.out.printf("Phone pluged to outlet with %dV voltage.\n",
                outlet.getVoltage());
    }
    
    public void unplugFromOutlet() {
        this.powerAdapter = null;
        System.out.println("\nPhone unpluged from outlet.\n");
    }

    public void charge() {
        powerAdapter.getPowerFromOutlet();
        System.out.println("Charging...");
    }
}
