JAVA2) Quiz #3

지우·2026년 1월 4일

java2

목록 보기
15/15

#1

class Bird {
    public void fly()
}

class Penguin extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("펭귄은 날지 못한다.");
    }
}

Q. 해당 코드는 SOLID 원칙 중 어떤 원칙을 지키지 못했는지 쓰고, 문제를 해결하기 위한 코드를 작성하세요.


A. 이 코드는 LSP 원칙을 지키지 않은 코드입니다. 자식 클래스가 부모 클래스의 행위를 깨지 않도록 재설계 해야 합니다.

interface Bird {
    void move();
}

class FlyingBird implements Bird {
    public void move() { System.out.println("날아요"); }
}

class WalkingBird implements Bird {
    public void move() { System.out.println("걸어요"); }
}

#2

class Light {
    public void turnOn() {
        System.out.println("💡 불 켜짐");
    }
    public void turnOff() {
        System.out.println("💡 불 꺼짐");
    }
}

class SmartHomeSwitch {
    private Light light;

    public SmartHomeSwitch() {
        this.light = new Light(); // 구체 클래스에 직접 의존
    }

    public void operate(String command) {
        if (command.equals("on")) light.turnOn();
        else light.turnOff();
    }
}

Q. 위의 코드의 문제점들을 DIP 원칙을 이용하여 설명하고, 어떻게 수정해야할지 서술하세요.

A. SmartHomeSwitch 클래스는 현재 오직 Light만 제어 가능하여 이후 새로운 디바이스를 추가하거나 수정할 수 없습니다. 이는 구체적인 구현 클래스에 의존하지 말고 인터페이스나 추상 클래스에 의존해야한다는 DIP 원칙에 어긋납니다.
-> SmartHomeSwitch 클래스는 Device 추상화에만 의존하도록 수정하고, 어떤 기기든 Device만 구현하면 즉시 연결할 수 있도록 해야 합니다. 또한 의존성 주입을 통해 객체를 유연하게 교환할 수 있도록 하는 과정도 필요합니다.

#3

Q. 다음 중 제어의 역전에 대해 틀린 말을 하고 있는 학생을 고르세요.

🤓 A 학생 : 의존성 주입은 제어의 역전을 구현하는 대표적인 기술로, 생성자 주입, setter 주입, 필드 주입 등의 구현 방법이 있어.

🤓 B 학생 : 제어의 역전은 객체 관리부터 서비스의 동작까지 모든 것을 개발자가 아닌, 프레임워크에 위임하는 것으로 개발자는 어떤 부품이 필요한지만 알려주고, 조립은 프레임워크가 알아서 해주는 원리야.

🤓 C 학생 : 의존성 주입 중 생성자 주입 방법은 final 키워드를 사용할 수 있어, 한번 주입받은 의존성이 런타임에 변경되는 것을 방지해준다는 장점이 있어. 또한 객체 생성 시점에서 모든 필수 의존성이 주입되어야 하므로 의존성이 누락되는 경우가 없어, 필수 의존성이 명확하고 안전성이 보장되어 스프링에서 가장 권장하는 방식이야.


A. B 학생
제어의 역전에서 프레임워크의 역할은 객체 관리부터 흐름 제어입니다. 프레임워크는 객체를 생성하고 모든 제어의 흐름을 관리할 뿐, 서비스가 실제로 어떻게 동작해야 하는지는 개발자가 알려줘야할 내용입니다. 따라서 개발자는 어떤 객체가 필요한지 프레임워크에 알려주고, 프레임워크는 이를 기반으로 조립을 해주는 역할을 합니다.

#4

Q. 다음 코드는 커피메이커를 이용해 커피를 생성하는 프로그램입니다. Espresso나 Americano 클래스를 수정하지 않고, 시럽을 추가하는 기능을 추가해보세요.

public interface CoffeeMachine {
    String brew();
}

public class EspressoMachine implements CoffeeMachine {
    @Override
    public String brew() {
        return "Extracting espresso";
    }
}

public class DripCoffeeMachine implements CoffeeMachine {
    @Override
    public String brew() {
        return "Dripping coffee";
    }
}

public class MilkFrother {
    public String frothMilk() {
        return "Frothing milk";
    }
}

public interface Coffee {
    String prepare(); 
}


public class Espresso implements Coffee {
    private final CoffeeMachine espressoMachine;

    public Espresso(CoffeeMachine espressoMachine) {
        this.espressoMachine = espressoMachine;
    }
    @Override
    public String prepare() {
	      System.out.print("에스프레소 준비 : ");
        return espressoMachine.brew();
    }
}


public class Americano implements Coffee {
    private final CoffeeMachine espressoMachine;
    public Americano(CoffeeMachine espressoMachine) {
        this.espressoMachine = espressoMachine;
    }
    @Override
    public String prepare() {
        System.out.print("아메리카노 준비 : ");
        return espressoMachine.brew() + " + hot water";
    }
}


public class Latte implements Coffee {
    
    private final Coffee espresso;       
    private final MilkFrother milkFrother; 

    public Latte(Coffee espresso, MilkFrother milkFrother) {
        this.espresso = espresso;
        this.milkFrother = milkFrother;
    }
    @Override
    public String prepare() {
        System.out.print("라떼 준비 : ");
        return espresso.prepare() + " + " + milkFrother.frothMilk();
    }
}


public class CoffeeMaker {
    private Coffee coffee;
    
    public void setCoffee(Coffee coffee) { // 이번에는 setter DI
        this.coffee = coffee;
    }
    public void makeCoffee() {  
        System.out.println(coffee.prepare());
    }
}
public class Main {
    public static void main(String[] args) {
        CoffeeMachine espressoMachine1 = new EspressoMachine();
        CoffeeMachine espressoMachine2 = new DripCoffeeMachine();
        MilkFrother milkFrother = new MilkFrother();

        Coffee espresso = new Espresso(espressoMachine1);
				System.out.println(espresso.prepare());
				
        Coffee latte = new Latte(espresso, milkFrother);
				System.out.println(latte.prepare());
				
        CoffeeMaker maker = new CoffeeMaker();
        maker.setCoffee(new Latte(espresso, milkFrother));
        maker.makeCoffee();
    }
}

A.

class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
    @Override
    public String prepare() {
        return decoratedCoffee.prepare();
    }
}

class Syrup extends CoffeeDecorator {
	public Syrup(Coffee coffee) {
    	super(coffee);
    }
    @Override
    public String prepare() {
    	return super.prepare() + " + Syrup";
    }
}

0개의 댓글