
ImageViewer라는 인터페이스를 정의하고, 시스템은 이 인터페이스만을 신뢰한다.PngImage, JpegImage, GifImage)는 고유 메서드를 제공하지만, ImageViewer와 호환되지 않는다.PngAdapter, JpegAdapter, GifIAdapter)를 정의하고, 이들은 ImageViewer를 구현한다.display() 메서드에서 그 객체의 기능 메서드를 호출한다.public class Main {
public static void main(String[] args) {
ImageViewer[] box = new ImageViewer[3];
box[0] = new PngAdapter(new PngImage());
box[1] = new JpegAdapter(new JpegImage());
box[2] = new GifIAdapter(new GifImage());
for (ImageViewer i : box){
i.display();
}
}
}
// 기존 이미지 뷰어
interface ImageViewer {
public abstract void display(); // public abstract는 생략되곤 한다. default를 붙이면(안붙이면 abstract가 자동이므로) 상속자가 선택적으로 오버라이드할 수 잇다.
}
// 이미지 클래스
class PngImage {
public void renderPng(){
System.out.println("PNG 이미지를 렌더링합니다.");
}
}
class JpegImage {
public void drawJpeg(){
System.out.println("JPEG 이미지를 그립니다.");
}
}
class GifImage {
public void animateGif() {
System.out.println("GIF 애니메이션을 실행합니다.");
}
}
// 어뎁터 클래스 <- 기존이미지 뷰어의 display로 각 이미지 클래스가 작동할 수 있게함.
class PngAdapter implements ImageViewer{
private PngImage png; // 연결시킬 클래스의 객체를 필드값으로 갖는다.
PngAdapter(PngImage png){
this.png = png;
}
@Override
public void display() { // 기존의 작동방식으로 새로운 기능을 구현
png.renderPng();
}
}
class JpegAdapter implements ImageViewer{
private JpegImage jpeg;
JpegAdapter(JpegImage jpeg){
this.jpeg = jpeg;
}
@Override
public void display() {
jpeg.drawJpeg();
}
}
class GifIAdapter implements ImageViewer{
private GifImage gif;
GifIAdapter(GifImage gif){
this.gif = gif;
}
@Override
public void display() {
gif.animateGif();
}
}
instanceof를 통해 각 어댑터의 고유 기능(setEqualizer, boostVolume)을 조건적으로 처리하였다.(1단계 → 어댑터 패턴으로 인터페이스 통합)
외부 라이브러리 클래스는 각기 다른 메서드와 상태 명칭을 가지므로, AudioControlUnit 인터페이스로 추상화한 어댑터 클래스를 구현한다.
(2단계 → 클라이언트에서 인터페이스 기반 처리)
List<AudioControlUnit> 형태로 어댑터들을 저장하고, play, activate, logPlay 메서드를 반복문으로 호출함으로써 포맷에 관계없는 일관된 재생 흐름을 구성한다.
(3단계 → 개별 포맷별 고유 기능 분기 처리)
instanceof로 타입을 체크한 후 Mp3Adapter의 setEqualizer, FlacAdapter의 boostVolume 등 추가 기능을 조건적으로 수행한다.
public class Main {
public static void main(String[] args) {
List<AudioControlUnit> box = new ArrayList<>();
box.add(new Mp3Adapter(new Mp3Service()));
box.add(new FlacEngineAdapter(new FlacEngine()));
box.add(new OggToolAdapter(new OggTool()));
for (AudioControlUnit i : box) {
i.play();
i.activate();
i.logPlay();
}
System.out.println("---------------------");
for (AudioControlUnit i : box) {
System.out.println(i.getFormatName());
System.out.println(i.isActive() ? "활성":"비활성");
i.getLog();
if (i instanceof Mp3Adapter){
((Mp3Adapter)i).setEqualizer("Bass");
}
else if (i instanceof FlacEngineAdapter) {
((FlacEngineAdapter) i).boostVolume(50);
}
}
}
}
// 기존 인터페이스
interface AudioControlUnit {
void play();
String getFormatName();
boolean isActive();
void activate();
void logPlay();
String getLog();
}
// 외부 라이브러리들(이라하자 하는 클래스)
class Mp3Service {
private boolean enabled = false;
public boolean isEnabled() {
return enabled;
}
public void mp3Play(){
System.out.println("mp3가 재생됩니다.");
}
public String getMp3Type(){
return "MP3";
}
public void setEqualizer(String mode){
System.out.printf("%s모드로 세팅되었습니다.\n", mode);
}
public void turnMp3(){
if (enabled) enabled = false;
else enabled = true;
}
public boolean MP3status(){
return enabled;
}
}
class FlacEngine {
private boolean enabled = false;
public boolean isEnabled() {
return enabled;
}
void executeFlac() {
System.out.println("Flac을 실행합니다.");
}
String format(){
return "FLAC";
}
void boostVolume(int level){
System.out.printf("볼륨을 %d로 조정합니다.\n", level);
}
public void turnFlac(){
if (enabled) enabled = false;
else enabled = true;
}
public boolean Flacstatus(){
return enabled;
}
}
class OggTool {
private boolean enabled = false;
public boolean isEnabled() {
return enabled;
}
void runOgg(){
System.out.println("ogg를 실행합니다.");
}
String info(){
return "OGG";
}
public void turnOgg(){
if (enabled) enabled = false;
else enabled = true;
}
public boolean Oggstatus(){
return enabled;
}
}
// 기존 인터페이스에 외부 라이브러리를 연결시키기 위한 어댑터 클래스
class Mp3Adapter implements AudioControlUnit {
private Mp3Service mp3;
List <LocalDateTime> list = new ArrayList();
public Mp3Adapter(Mp3Service mp3) {
this.mp3 = mp3;
}
void setEqualizer(String mode){
if (mp3.isEnabled()){
System.out.printf("EQ를 %s로 설정합니다.\n", mode);
}
}
@Override
public void activate() {
mp3.turnMp3();
System.out.println("mp3가 활성화되었습니다.");
}
@Override
public String getFormatName() {
return mp3.getMp3Type();
}
@Override
public String getLog() {
return list.get(list.size()-1).toString();
}
@Override
public boolean isActive() {
return mp3.MP3status();
}
@Override
public void logPlay() {
list.add(LocalDateTime.now());
}
@Override
public void play() {
mp3.mp3Play();
}
}
class FlacEngineAdapter implements AudioControlUnit {
private FlacEngine flacEngine;
List <LocalDateTime> list = new ArrayList();
public FlacEngineAdapter(FlacEngine flacEngine) {
this.flacEngine = flacEngine;
}
@Override
public void activate() {
flacEngine.turnFlac();
System.out.println("Flac이 활성화되었습니다.");
}
@Override
public String getFormatName() {
return flacEngine.format();
}
@Override
public String getLog() {
return list.get(list.size()-1).toString();
}
@Override
public boolean isActive() {
return flacEngine.Flacstatus();
}
@Override
public void logPlay() {
list.add(LocalDateTime.now());
}
@Override
public void play() {
flacEngine.executeFlac();
}
public void boostVolume(int level){
if (flacEngine.isEnabled()){
System.out.printf("볼륨을 %s로 설정합니다.\n", level);
}
}
}
class OggToolAdapter implements AudioControlUnit {
private OggTool oggTool;
List <LocalDateTime> list = new ArrayList();
public OggToolAdapter(OggTool oggTool) {
this.oggTool = oggTool;
}
@Override
public void activate() {
oggTool.turnOgg();
System.out.println("ogg가 활성화되었습니다.");
}
@Override
public String getFormatName() {
return oggTool.info();
}
@Override
public String getLog() {
return list.get(list.size()-1).toString();
}
@Override
public boolean isActive() {
return oggTool.Oggstatus();
}
@Override
public void logPlay() {
list.add(LocalDateTime.now());
}
@Override
public void play() {
oggTool.runOgg();
}
}