반응형

가정)

나는 오리 연못 시뮬레이션 개임을 만드는 회사에 다니고 있다.

이 게임에서는 헤엄도 치고 꽥꽥거리는 소리도 내는 매우 다양한 오리 종류를 보여줄 수 있다.

 

.

.

.

public abstract class Duck {
    //울기
    abstract void quack();
    //수영
    abstract void swim();

}

오리의 종류들 마다 다르지만, 오리 객체를 상속 받아서, 울기와 수영하기 메소드를 @override하였다.

class JustDuck extends Duck {

    @Override
    void quack() {
        //울기
    }

    @Override
    void swim() {
        //수영하기
    }
}

.

.

.

 

가정)

작년부터 다른 경쟁사로부터의 압박이 점점 심해졌다.

다음 주에 회사에서 있을 주주총회 때 뭔가 정말 인상적인 것을 보여줘야만 한다..

 

나는 오리를 날수도 있게 메소드를 추가 하였고 JustDuck에서도 override 하게 만들었다.

 

public abstract class Duck {
    //울기
    abstract void quack();
    //날기
    abstract void swim();
    abstract void fly();
}

class JustDuck extends Duck {
    @Override
    void quack() {
        //울기
    }
    @Override
    void swim() {
        //수영하기
    }
   @Override
    void fly() {
        //날기
    }
}

 

.

.

.

가정) 그런데 심각한 문제가 생겼다.

모든 오리가 날 수 있는게 아니였다.. 장난감오리는 날 수 없다.

어떻게 해결 할 것인가?.

 

상속을 사용하는 것은 올바른 해결책이 아니라는 것을 알 수 있다.  

 

디자인 원칙 : 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리시킨다.

해결 방법 : 바뀌는 부분을 찾아서 나머지 코드에 영향을 주지 않도록 "캡슐화" 합니다.

                 이렇게 하면, 나중에 바뀌지 않는 부분에는 영향을 미치지 않은 채로 그 부분만 고치거나 확장할 수 있다.

 

 

fly()와 quack()은 Duck클래스에서 오리마다 달라지는 부분입니다.

이러한 행동을 Duck 클래스로부터 갈라내기 위해서 그 두 메소드를 모두 Duck 클래스로부터 끄집어 내서,

각 행동을 나타낼 클래스 집합을 새로 만들도록 하겠습니다.

 

디자인 원칙 : 구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.

 

//상속(abstract)가능 클래스
public abstract class Duck {

    //구성 (행동을 위임 받는 것.)
    FlyBehavior flyBehavior;

    public Duck() { }

    public String howToFly() {
        return flyBehavior.fly();
    }

}


//인터페이스
public interface FlyBehavior {
    //String을 반환하는 메소드
    String fly();
}

//
public class CantFly implements FlyBehavior{
    @Override
    public String fly() {
        return "날고 싶어도 못날아요~";
    }
}

//날지못하는 행동을 가진 justDuck 클래스
class JustDuck extends Duck{
    //오리클래스를 상속 받음. 상속을 받음으로서, flyBehavior 객체를 위임 받아, 행동을 구현.
    public JustDuck() {
        flyBehavior = new CantFly();
    }
}
public class MainActivity2 extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        Duck justDuck = new JustDuck();
        justDuck.howToFly();
        Log.d("abcd","날 수는 있니? "+justDuck.howToFly());
    }
}


결과 : 날 수는 있니? 날고 싶어도 못날아요~

 

디자인 원칙 : 상속보다는 구성을 활용한다.

 

 

 

------------------- kotlin -------------------

 

open class Duck {

    var flyBehavior:FlyBehavior? = null

    fun howToFly() : String? {

        return flyBehavior?.fly()
    }
}


//
interface FlyBehavior {

    fun fly() : String?
}


//
class CantFly : FlyBehavior{
    override fun fly(): String {
        return "날고 싶어도 못날아용~"
    }
}


//
class JustDuck : Duck() {
    init {
        flyBehavior = CantFly()
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val justDuck:Duck = JustDuck()
        Log.d("abcd","결과 : "+justDuck.howToFly())
    }
}


결과 : 날고 싶어도 못날아용~

 

반응형

+ Recent posts