-
객체지향과 디자인패턴 1언어/객체지향 2023. 8. 11. 11:05
1. 지저분한 코드
최초 요구사항: 메뉴영역에 메뉴1과 메뉴2가 있다. 공통영역에 버튼 1이 있다.
- 메뉴를 누르면 각 메뉴로 화면전환
-버튼을 누르면 각 메뉴에 맞는 화면처리를 한다.
public class Application implements OnClickedListener { private Menu menu1 = new Menu("menu1"); private Menu menu2 = new Menu("menu2"); private Button button1 = new Button("bu1"); private String currentMenu = null; public Application(){ menu1.setOnClickListener(this); // 클릭시 이벤트 담당하는 클래스 등록 menu2.setOnClickListener(this); button1.setOnClickListener(this); } public void clicked(Component eventSource){ if(eventSource.getId().equals("menu1")) changeUIToMenu1(); else if (eventSource.getId().equals("menu2")) changeUIToMenu2(); else if (eventSource.getId().equals("button1")) if(currentMenu == null) return; if(currentMenu.equals("menu1")) precessButton1WhenMenu1(); else if (currentMenu.equals("menu2")) { processButton1WhenMenu2(); } } private void processButton1WhenMenu2() { //.. } private void precessButton1WhenMenu1() { //.. } private void changeUIToMenu2() { //.. } private void changeUIToMenu1() { //.. } }
- 두 개의 메뉴와 한 개의 버튼에서 이벤트가 발생하면, 그 이벤트를 clicked()메서드에서 처리한다. (각 버튼에 OnClickedListener 클래스(clicked 메서드 가짐) 등록
- 위 클래스는 하나의 클래스가 메뉴1,2,버튼1도 포함하면서, 화면처리 이벤트도 처리한다.
- 이런경우 만약 메뉴3과 버튼2가 포함된다고 가정해보자. -> 메뉴와 버튼 클릭처리를 위해 if-else구조가 중첩될 것이다.
- 하나의 클래스에서 여러 버튼의 책임을 혼자서 책임지려다보니 코드가 복잡해진다.
2. 수정하기 좋은 코드로 변경
- 이 상황을 객체 지향 방식으로
- 요구사항을 다시 생각해보면, 메뉴가 선택되면 해당 화면을 보여준다. 버튼이 클랙되면 선택된 메뉴에 맞는 처리를 한다.
- 위 두개의 공통 동작을 인터페이스화 해보자
- 인터페이스
public interface ScreenUI { public void show(); public void handleButton1Click(); }
- 구현체
public class Menu1UI implements ScreenUI { @Override public void show() { //.. } @Override public void handleButton1Click() { //.. } }
public class Application implements OnClickedListener { private Menu menu1 = new Menu("menu1"); private Menu menu2 = new Menu("menu2"); private Button button1 = new Button("bu1"); private ScreenUI currentMenu=null; public Application(){ menu1.setOnClickListener(this); menu2.setOnClickListener(this); button1.setOnClickListener(this); } public void clicked(Component eventSource){ String ev = eventSource.getId(); if(ev.equals("menu1")) { currentMenu = new Menu1UI(); currentMenu.show(); } else if (ev.equals("menu2")) { currentMenu = new Menu2UI(); currentMenu.show(); } else if (ev.equals("button1")) { if(currentMenu==null)return; currentMenu.handleButton1Click(); } }
- 버튼1을 클릭을 처리하는 코드는 현재 화면이 메뉴1인지 2인지 상관없이, currentMenu에 handleButtonClick()를 호출한다.
- 위와 같이 수정할 수 있다. 각 메뉴화면과 버튼 클릭시 처리에 대한 책임을 메뉴가 가지도록 변경했다.
- 메뉴3이나, 버튼이 추가되면, 이전과 다르게 ScreenUI를 구현한 메뉴3을 추가 혹은 button2를 처리하는 메서드를 ScreenUI에 추가해서 각 클래스별로 구현하도록 하면 된다.
3. clicked메서드에서 버튼을 처리하는 것과 메뉴 처리하는 것 분리
private ScreenUI currentMenu=null; public Application(){ menu1.setOnClickListener(menuListener); menu2.setOnClickListener(menuListener); button1.setOnClickListener(buttonListener); } private OnClickedListener menuListener = new OnClickedListener() { @Override public void clicked(Component eventSource) { String ev = eventSource.getId(); if (ev.equals("menu1")) { currentMenu = new Menu1UI(); } else if (ev.equals("menu2")) { currentMenu = new Menu2UI(); currentMenu.show(); } } }; private OnClickedListener buttonListener = new OnClickedListener() { @Override public void clicked(Component eventSource) { if (currentMenu == null) return; String ev = eventSource.getId(); if (ev.equals("button1")) currentMenu.handleButton1Click(); } };
- 메뉴와 버튼이 다른 OnClickedListener를 등록하도록 하여, 클릭시 서로 다른 clicked()가 호출됨
- 각 메뉴와 버튼은 메뉴와 버튼이 추가, 삭제 될 때 마다 바뀔텐데 기존처럼 하나의 메서드에서 이를 다 처리하면, 가독성이 떨어진다.
- 객체지향코드로 바뀌면서 클래스가 추가되었지만, 기존보다 유지보수가 쉬워졌다.
> 새로운 메뉴 추가시 버튼 처리 코드가 영향 받지 않는다.(clicked())
> 한 메뉴 관련 코드가 하나의 클래스로 모여서 코드 분석 수정이 용이하다.
> 서로 다른 메뉴에 대한 처리 코드가 섞여 있지 않아 수정이 용이하다.
- 각 객체의 책임을 분리하여 다른 클래스로 작성하였기 때문에, 특정 객체를 수정해야할 때 불필요하게 다른 객체의 코드를 볼 필요가 없어졌다.
'언어 > 객체지향' 카테고리의 다른 글
객체 지향과 디자인 패턴 - 다형성과 추상 타입 (0) 2023.08.13 객체지향과 디자인패턴 2 (0) 2023.08.13 객체지향의 사실과 오해 3 (0) 2023.08.02 객체지향의 사실과 오해 2 (0) 2023.08.02 객체지향의 사실과 오해 (0) 2023.08.01