interface Device {
boolean isEnabled();
void enable();
void disable();
int getVolume();
void setVolume(int percent);
}
class TV implements Device {
private boolean on = false;
private int volume = 30;
public boolean isEnabled() { return on; }
public void enable() { on = true; }
public void disable() { on = false; }
public int getVolume() { return volume; }
public void setVolume(int percent) { volume = percent; }
}
class Radio implements Device {
private boolean on = false;
private int volume = 20;
public boolean isEnabled() { return on; }
public void enable() { on = true; }
public void disable() { on = false; }
public int getVolume() { return volume; }
public void setVolume(int percent) { volume = percent; }
}
class Remote {
protected Device device;
Remote(Device device) { this.device = device; }
void togglePower() {
if (device.isEnabled()) device.disable();
else device.enable();
}
void volumeDown() {
device.setVolume(device.getVolume() - 10);
}
void volumeUp() {
device.setVolume(device.getVolume() + 10);
}
}
public static void main(String[] args) {
TV tv = new TV();
Remote remote = new Remote(tv);
remote.togglePower();
remote.volumeUp();
}The Bridge pattern decouples an abstraction from its implementation so that the two can vary independently. It uses composition over inheritance by separating the abstraction (the high-level control logic) from the implementation (the platform-specific details) into separate class hierarchies. This is useful when both the abstraction and the implementation may need to be extended independently.