한 설계 부품(클래스, 함수..)는 하나의 책임만 가져야 한다. 약은 약사에게 진료는 의사에게… 한 부품에 여러 기능이 있으면, 내부 메소드들이 의지하는 부분이 많아진다. 즉 결합도가 높아지고, 그 부품에 대한 책임 높아진다. -> 유지보수가 힘들어진다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classICanDoEverything{ publicvoidplus(int a, int b){ System.out.println(a+b); }; publicvoiddisplay(Displayable file){file.play();} publicvoidsingASong(Singable singer){singer.sing();} } publicclassSRPTest{ publicstaticvoidmain(String[] args){ ICanDoEverything hero = new ICanDoEverything(); Displayable file = new Jpg(); Singable singer = new RealSinger(); int a1 = 1; int a2 =2; hero.display(file); //책임 1 hero.singASong(singer); //책임 2 hero.plus(a1, a2);//책임 3 } }
숫자 두개를 더하고, 파일을 받아 실행하고, 가수를 불러 노래도 시킬 수 있는 ICanDoEverything 클래스가 있다! 이 클래스의 객체 hero는 main메서드에서 3가지 책임을 하고 있다. 근데 만약 이 클래스의 한 메서드에서 문제가 생기면 어떨까? 객체 hero의 3가지 책임이 모두 실행할 수 없게 된다!!!(그 책임이 문제와 큰 관련이 없어도 말이다)
O : 개방-폐쇄 원칙(OCP)
기존의 코드를 변경하지 않고(close) 기능을 수정하거나 추가 할 수 있어야 한다.(open) 자주 변경되는 내용은 따로 분리하고, 자주 변경되지 않는 부분은 다른 부분이 변경 되더라도 영향을 덜 받아야 한다.
@Override publicvoidsing(){ System.out.println("Singer can sing a song!!"); }
@Override publicvoidswim(){ System.out.println("Singer can swim....?"); } }
노래를 하는 Singer클래스는 여러 기능을 포함하는 큰 인터페이스를 구현하고 있다. 이에 대한 부작용으로 Singer클래스는 자신이 해야할 역할 외에도 다른 기능을 구현해야 하게 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
interfaceSingable{ voidsing(); } interfaceRunnable{ voidrun(); } interfaceSwimable{ voidswim(); } classRealSingerimplementsSingable{ @Override publicvoidsing(){ System.out.println("Singer can sing a song~!"); } }
인터페이스를 구체적으로 나눴더니, Singer클래스가 필요한 역할만 구현할 수 있게 됐다!
D : 의존 역전 원칙(DIP)
의존 관계를 맺을 때, 변하기 쉬운 것보다 변화하기 어려운 것에 의존해라! 변화하기 쉬운 것 -> 구체적으로 구현된 것 변화하기 어려운 것 -> 추상화 된 것(인터페이스, 추상 클래스)
즉 의존관계를 맺을 때, 실제 구현된 클래스가 아닌 인터페이스나 추상 클래스과 맺으라는 뜻!!
역전?
즉 원래 변하기 쉬운 것에 상위 모듈이 의존하면 : 변화할때마다 상위 모듈도 따라 변화해야 함! 그러나 인터페이스 같이 변하기 어려운 것에 상위 모듈이 의존하면? 하위 모듈은 인터페이스에 의존하도록 하여(역전!), 수정을 아무리 해도 상위 모듈이 인터페이스를 의존하는 한 문제는 없다!
1 2 3 4 5 6 7 8 9 10 11 12 13
publicclassImageDisplay{
publicstaticvoidmain(String[] args){ FileDisplayer fileDisplayer = new FileDisplayer(); Displayable file = new Jpg(); fileDisplayer.setFile(file); fileDisplayer.play();
file = new Gif(); fileDisplayer.setFile(file); fileDisplayer.play(); } }
아까 사용했던 예시에서 보면, 실제 구현된 Jpg 클래스의 메소드를 부르는게 아닌, Diplayable 인터페이스의 메소드를 호출하는 방식으로 의존관계를 만든다!!