### 소개 > "**책**은 몇 번 읽었는데.. 막상 **코딩**을 하려면 뭐 부터 해야할지 모르겠어요.." > "**객체지향 프로그래밍**이라는게 잘 이해가 잘 안됩니다.." > "자바를 배우면 **무얼 만들 수 있죠?**" ### 진행방향 + 문제를 주어주고, 이를 해결하기 위한 개념을 토의하며, 이를 바탕으로 실제 프로그램을 만듭니다. ### 목표 + 자바 기본문법을 숙지 + 객체지향 프로그래밍의 이해 + 객체지향적 프로그램 설계능력 향상 + 프로그램 구현 능력 증진 ### 교재 + [**MIT Introduction to Programming in Java**](https://goo.gl/Kl5I19) - Types, variables, operators - More types, methods, conditionals - Loops and arrays - Objects and classes - Access control, class scope, packages, Java API - Design, debugging, interfaces - Inheritance, exceptions, file I/O ### 시간 및 장소 + 매주 월요일 7시 - 9시 / 총 8주 과정 + 신림역 통스토리 ![](https://www.dropbox.com/s/ibhv7no6cz4lydq/silim.png?dl=1) ### 인원 + 2~4 명 ### 비용 + 10 만원(4주 기준, 총 8주) ### 연락처 + 이메일: [email protected] + 카 톡: chaesam
# 자기소개하기 ### 상황설정 이제 막 대학교 새내기각 된 박컴돌(20) 학생. 난생 처음 자바라는 것을 배우고, 첫 과제를 부여 받게 되는데.. ### 요구사항 아래와 같이 동작하는 자기소개를 하는 프로그램을 작성하시오. ![](https://www.dropbox.com/s/cp3tu7z5kta91um/0101.png?dl=1) ### 예시코드 ```java import java.util.Scanner; public class SelfIntroduction { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.printf("이름을 입력하세요: "); String name = scanner.next(); System.out.println(); System.out.println(name + " 학생~ 프로그래밍 입문을 축하합니다~"); System.out.println("웰컴 투 헬~ (\\ .. /)/"); } } ```
# 달러 환전하기 ### 상황설정 우연찮게 도박 사이트에 접속하게 된 박컴돌(21) 학생. 주사위 도박 게임에 빠지고 마는데.. > 게임 룰: > 주사위를 던져 큰 수가 나온 사람이 달러를 획득한다. > 획득 달러량은 주사위의 수와 같다. ### 요구사항 + 1에서 6사이의 숫자를 반환한 뒤, 그 숫자에 달러 환율을 곱하여 결과값을 출력하시오. + 환율은 1달러 = 1116.07143원으로 한다.(2016.10.10 기준) ![](https://www.dropbox.com/s/ihfvrc7qg0gpai6/0201.png?dl=1) ### 예시코드 ```java public class DiceGambling { public static void main(String[] args) { int n = 1 + (int)(Math.random() * 1000) % 6; double dallarRate = 1116.07143; double krw = n * dallarRate; System.out.println(n + " 달라 = " + krw + " 원"); } } ```
# 비만도 검사하기 ### 상황설정 '학교-집-학교-집'을 반복하며 밤낮없이 전공 공부와 과제를 작성해오던 박컴돌(21) 학생. 항상 컴퓨터 앞에서 떠날 줄 모르고.. 그렇게 몸매는 망가져만 가는데.. ### 요구사항 키와 몸무게를 입력받아 비만도를 측정해주는 프로그램을 작성하시오. 비만도는 [BMI지수](https://goo.gl/KFn4wX)를 사용하여 네 가지 단계(저체중, 정상, 과체중, 비만)로 구분 할 것. ![](https://www.dropbox.com/s/xy2krulluitot8c/0301.png?dl=1) ### 예시코드 ```java import java.util.Scanner; public class BMICalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("키와 몸무게를 입력하시오. [예] 182.4 75.5"); double tall = scanner.nextDouble() / 100; double weight = scanner.nextDouble(); double bmi = weight / (tall * tall); if (bmi < 18.5) System.out.println("저체중 입니다."); else if (bmi < 23) System.out.println("정상 입니다."); else if (bmi < 25) System.out.println("과체중 입니다."); else System.out.println("비만 입니다."); } } ```
# 펀치머신 ### 상황설정 이태원에 놀러간 박컴돌(21) 학생. 친구들과 함꼐 맛나는 음식과 시원한 맥주를 마시고 돌아오는 길에서 펀치 머신과 마주하게 된다.. ### 요구사항 아래의 기록을 참고하여 가장 고득점자를 찾는 프로그램을 만드시오. ![](https://www.dropbox.com/s/9cj59pxlj2ewllr/0401.png?dl=1) |이름|점수| |:--|:--| |Elena|590| |Thomas|252| |Hamilton|562| |Suzie|251| |Phil|519| |Matt|408| |Alex|870| |Emma|646| |John|185| |James|620| |Emily|577| |Daniel|633| |Neda|937| |Aaron|380| |Kate|285| ### 예시코드 ```java public class Punch { public static void main(String[] args) { String[] names = { "Elena", "Thomas", "Hamilton", "Suzie", "Phil", "Matt", "Alex", "Emma", "John", "James", "Emily","Daniel", "Neda", "Aaron", "Kate" }; int[] scores = {590, 252, 562, 251, 519, 408, 870, 646, 185, 620, 577, 633, 937, 380, 285}; int highScoreIdx = 0; for (int i = 0; i < scores.length; i++) if (scores[highScoreIdx] < scores[i]) highScoreIdx = i; System.out.println("최고득점자는 " + names[highScoreIdx] + " 입니다."); } } ```
# 대전 게임 만들기 I ### 상황설정 평소 알피지 게임을 좋아하던 박컴돌(21) 학생. 어느날 무자비한 PK를 당하고 만다. 아무리 싸워도 이길 수 없음을 깨닫고, 결국 게임을 접고야 만다. > "아오 빡쳐.. 내가 게임을 만들면, 아무도 날 못이기겠지..?" ### 요구사항 아래와 같이 동작하는 두 영웅의 대전 게임을 구현하시오. ![](https://www.dropbox.com/s/4qlbscdst9f6kpw/0501.jpg?dl=1) + 영웅은 다음과 같은 속성을 갖는다. - 이름 - 체력 (모든 영웅의 기본체력은 100으로 동일) + 영웅은 펀치를 통해 상대 영웅에게 피해를 입힐 수 있다. - 펀치는 랜덤하게 발동된다. + 게임은 두 영웅의 생성과 동시에 시작되며 하나가 죽을 때까지 진행된다. ### 설계 ![](https://www.dropbox.com/s/fl1flo8uk0wwzac/0502.jpg?dl=1) ### 구현 ```java import java.util.Random; public class Hero { private String name; private int hp = 100; // 생성자 public Hero(String name) { this.name = name; } // 펀치 public void punch(Hero enermy) { enermy.hp -= 10; System.out.printf("[%s]의 펀치\n", this.name); System.out.printf("\t%s: %d/100\n", enermy.name, enermy.hp); } // 테스트 코드 public static void main(String[] args) throws InterruptedException { Hero arthas = new Hero("아서스"); Hero leona = new Hero("레오나"); Random random = new Random(); while (arthas.hp > 0 && leona.hp > 0) { Boolean isArthasTurn = random.nextBoolean(); Hero attacker = isArthasTurn ? arthas : leona; Hero defender = isArthasTurn ? leona : arthas; attacker.punch(defender); Thread.sleep(1000); } } } ``` ### 실행결과 <div class="embed-responsive embed-responsive-4by3"> <iframe class="embed-responsive-item" src="https://www.youtube.com/embed/Ojq_T378_mE"></iframe> </div>
# 그래픽 API: 움직이는 박스들 ### 학습목표 + Access Control + Class Scope + Packages + Java API ### 과제5: Graphics I 우리는 객체를 만드는 방법에 대하여 배웠습니다. 객체사용의 장점은 다른사람들이 만든 코드를 쉽게 사용할 수 있다는 점입니다. (물론 다른 여러 장점들이 더 있습니다) 이번 과제에서는 Java API가 기본으로 제공하는 Graphics와 Containers를 사용함으로써 이를 경험해보도록 하겠습니다. ### 요구사항 1. 초기 화면에 3개의 다른 도형이 그려지도록 구현하시오. 2. BouncingBox 인스턴스를 사용하여 각각의 도형이 다른 방향으로 움직이도록 할 것. (ArrayList를 사용하여 도형들을 관리 할 것.) ### 초기설정 1. 이클립스로부터 프로젝트를 생성합니다. 2. 다음 3개의 클래스를 생성하고 주어진 소스코드를 복사하여 붙여넣습니다. - SimpleDraw - BouncingBox - DrawGraphics 3. 프로그램을 실행해 봅니다. 정상실행이 된 경우 아래의 화면이 나오게 됩니다. ![JF-Fig-5.2](https://www.dropbox.com/s/8nrldbsqjmu63fh/JF-Fig-5.2.png?dl=1) + 실행이 안되는 경우, **`Simple`**클래스를 선택 후 실행해보세요~ ### 스켈레톤 코드 + SimpleDraw.java ```java import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; /** Displays a window and delegates drawing to DrawGraphics. */ public class SimpleDraw extends JPanel implements Runnable { private static final long serialVersionUID = -7469734580960165754L; private boolean animate = true; private final int FRAME_DELAY = 50; // 50 ms = 20 FPS public static final int WIDTH = 300; public static final int HEIGHT = 300; private DrawGraphics draw; public SimpleDraw(DrawGraphics drawer) { this.draw = drawer; } /** Paint callback from Swing. Draw graphics using g. */ public void paintComponent(Graphics g) { super.paintComponent(g); // Enable anti-aliasing for better looking graphics Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); draw.draw(g2); } /** Enables periodic repaint calls. */ public synchronized void start() { animate = true; } /** Pauses animation. */ public synchronized void stop() { animate = false; } private synchronized boolean animationEnabled() { return animate; } public void run() { while (true) { if (animationEnabled()) { repaint(); } try { Thread.sleep(FRAME_DELAY); } catch (InterruptedException e) { throw new RuntimeException(e); } } } public static void main(String args[]) { final SimpleDraw content = new SimpleDraw(new DrawGraphics()); JFrame frame = new JFrame("Graphics!"); Color bgColor = Color.white; frame.setBackground(bgColor); content.setBackground(bgColor); // content.setSize(WIDTH, HEIGHT); // content.setMinimumSize(new Dimension(WIDTH, HEIGHT)); content.setPreferredSize(new Dimension(WIDTH, HEIGHT)); // frame.setSize(WIDTH, HEIGHT); frame.setContentPane(content); frame.setResizable(false); frame.pack(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } public void windowDeiconified(WindowEvent e) { content.start(); } public void windowIconified(WindowEvent e) { content.stop(); } }); new Thread(content).start(); frame.setVisible(true); } } ``` + BouncingBox.java ```java import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; public class BouncingBox { int x; int y; Color color; int xDirection = 0; int yDirection = 0; final int SIZE = 20; /** * Initialize a new box with its center located at (startX, startY), * filled with startColor. */ public BouncingBox(int startX, int startY, Color startColor) { x = startX; y = startY; color = startColor; } /** Draws the box at its current position on to surface. */ public void draw(Graphics surface) { // Draw the object surface.setColor(color); surface.fillRect(x - SIZE/2, y - SIZE/2, SIZE, SIZE); surface.setColor(Color.BLACK); ((Graphics2D) surface).setStroke(new BasicStroke(3.0f)); surface.drawRect(x - SIZE/2, y - SIZE/2, SIZE, SIZE); // Move the center of the object each time we draw it x += xDirection; y += yDirection; // If we have hit the edge and are moving in the wrong direction, reverse direction // We check the direction because if a box is placed near the wall, we would get "stuck" // rather than moving in the right direction if ((x - SIZE/2 <= 0 && xDirection < 0) || (x + SIZE/2 >= SimpleDraw.WIDTH && xDirection > 0)) { xDirection = -xDirection; } if ((y - SIZE/2 <= 0 && yDirection < 0) || (y + SIZE/2 >= SimpleDraw.HEIGHT && yDirection > 0)) { yDirection = -yDirection; } } public void setMovementVector(int xIncrement, int yIncrement) { xDirection = xIncrement; yDirection = yIncrement; } } ``` + DrawGraphics.java ```java import java.awt.Color; import java.awt.Graphics; public class DrawGraphics { BouncingBox box; /** Initializes this class for drawing. */ public DrawGraphics() { box = new BouncingBox(200, 50, Color.RED); } /** Draw the contents of the window on surface. Called 20 times per second. */ public void draw(Graphics surface) { surface.drawLine(50, 50, 250, 250); box.draw(surface); } } ``` ### 문제해결 #### Part One: Drawing Graphics 먼저 `DrawGraphics` 클래스를 열어줍니다. 초기 실행시 보이는 정사각형과 직선이 보이는데 이를 그려주는 메쏘드가 `draw` 입니다. **요구사항1**에서 3개의 도형을 그려달라 했으므로 우리는 하나의 다른 도형만 추가해 주면 되겠습니다~ (초기 2개의 도형을 지우고 다른 도형으로 바꾸셔도 됩니다~ Be Creative!) Java API에서 [java.awt.Graphics](http://docs.oracle.com/javase/8/docs/api/)를 참고하시면 직사각형, 직선, 타원, 등등 기타 여러가지 도형을 그릴 수 있는데, 저는 타원을 그려보겠습니다. + 타원 추가하기 - Java API에서 타원을 그리는 함수를 찾아보았습니다~ ![JF-Fig-5.3](https://www.dropbox.com/s/1cnbypc72l3f2id/JF-Fig-5.3.png?dl=1) - 클릭을 해보면 친절한(?) 영어설명이 되어있어요 -_-;; ![JF-Fig-5.4](https://www.dropbox.com/s/inqzwtatvbzq7e3/JF-Fig-5.4.png?dl=1) - 설명을 따라 타원을 그려보았습니다. ```java public void draw(Graphics surface) { surface.drawLine(50, 50, 250, 250); box.draw(surface); surface.drawOval(100, 100, 100, 200); } ``` ![JF-Fig-5.5](https://www.dropbox.com/s/hn9c0hp5a0swvgv/JF-Fig-5.5.png?dl=1) #### Part Two: Containers and Animation 우리가 만든 `DrawGraphics`클래스와 `BouncingBox`클래스는 애니메이션 효과를 지원합니다. `DrawGraphics`는 초당 20번 `draw`메쏘드를 호출함으로써 화면을 지속적으로 새로이 보여줍니다. `BouncingBox`에서는 박스의 움직임에 대한 설정을 `setMovementVector`메쏘드를 통해 제공합니다. 예를들면 `setMovementVector(1,0)`은 오른쪽방향으로 박스가 천천히 움직이고, `setMovementVector(0,-2)`는 위쪽으로 빠르게 움직입니다. 그럼 이제 **요구사항2**를 만족하기 위해 `DrawGraphics`클래스를 변경해봅시다. (`setMovementVector()`메쏘드는 DrawGraphics의 생성자에서 한번만 설정해 주면 됩니다) + BouncingBox 생성 - ArrayList를 만들고, 3개의 BouncingBox 인스턴스를 추가해주었습니다. ```java public class DrawGraphics { ArrayList<BouncingBox> boxes; public DrawGraphics() { boxes = new ArrayList<BouncingBox>(); // BouncingBox 생성자의 전달인자는 박스의 x, y 좌표와 색상입니다. BouncingBox boxA = new BouncingBox(200, 50, Color.RED); BouncingBox boxB = new BouncingBox(150, 50, Color.GREEN); BouncingBox boxC = new BouncingBox(100, 50, Color.BLUE); boxes.add(boxA); boxes.add(boxB); boxes.add(boxC); } ... } ``` - 다음으로 `draw`메쏘드를 통 박스를 그려주도록 하겠습니다~ ```java public class DrawGraphics { ... public void draw(Graphics surface) { surface.drawLine(50, 50, 250, 250); surface.drawOval(100, 100, 100, 150); for(BouncingBox box : boxes) { box.draw(surface); } } } ``` - 실행결과 ![JF-Fig-5.6](https://www.dropbox.com/s/5fgmlhqkp3hm51u/JF-Fig-5.6.png?dl=1) + BouncingBox 움직이기 - `DrawGraphics`의 생성자에서 이동속도를 설정해 줍니다~ ```java public DrawGraphics() { boxes = new ArrayList<BouncingBox>(); BouncingBox boxA = new BouncingBox(200, 50, Color.RED); BouncingBox boxB = new BouncingBox(150, 50, Color.GREEN); BouncingBox boxC = new BouncingBox(100, 50, Color.BLUE); boxA.setMovementVector(1, 2); boxB.setMovementVector(4, 3); boxC.setMovementVector(4, 3); boxes.add(boxA); boxes.add(boxB); boxes.add(boxC); } ``` - 실행해 봅니다~!! ![JF-Fig-5.7](https://www.dropbox.com/s/n9vw34xd6190z2k/JF-Fig-5.7.png?dl=1) ### 추가과제 **java.lang.Random** 클래스의 `nextInt(int bound)`메쏘드를 이용하여 매번 실행시 BouncingBox의 개수가 바뀌도록 만들어봅시다~~ ![JF-Fig-5.8](https://www.dropbox.com/s/3qjl5bpztx231it/JF-Fig-5.8.png?dl=1)
# 대전 게임 만들기 II ### 상황설정 나만의 게임을 만들기 시작한 박컴돌(21) 학생. 영웅에게 전직 시스템을 도입시키기로 하는데.. ### 요구사항 기존 대전 게임 시스템에 전직시스템을 추가 하시오. ![](https://www.dropbox.com/s/owsi5hks4mo34z8/0601.jpg?dl=1) + 영웅은 직업을 선택할 수 있다. - 기사 - 법사 + 기사는 체력이 추가되며, 배쉬를 사용 할 수 있다. - 체력: +100 - 배쉬: 데미지 30 + 법사는 체력이 추가되며, 파이어볼을 사용 할 수 있다. - 체력: +80 - 파이어볼: 데미지 35 + 게임은 두 영웅의 생성과 동시에 시작되며 둘중 하나가 죽을 때까지 서로 공격 한다. + 영웅이 공격 기회를 얻을 확률은 동일하다. + 모든 기술은 동일한 발동 확률을 지닌다. ### 설계 ![](https://www.dropbox.com/s/0cut5wz3n4dcmhe/0602.jpg?dl=1) ### 구현 **MainTest.java** ```java import java.util.Random; public class MainTest { // 테스트 코드 public static void main(String[] args) throws InterruptedException { Hero arthas = new Knight("아서스"); Hero leona = new Wizard("레오나"); Random random = new Random(); while (arthas.hp > 0 && leona.hp > 0) { Boolean isArthasTurn = random.nextBoolean(); Hero attacker = isArthasTurn ? arthas : leona; Hero defender = isArthasTurn ? leona : arthas; attacker.attack(defender); Thread.sleep(1000); } } } ``` **Hero.java** ```java public class Hero { protected String name; protected int hp = 100; // 생성자 public Hero(String name) { this.name = name; } // 펀치 public void punch(Hero enermy) { enermy.hp -= 10; System.out.printf("[%s]의 ☞ 펀치 ☞\n", this.name); System.out.printf("\t%s: %d\n", enermy.name, enermy.hp); } // 공격 public void attack(Hero enermy) { punch(enermy); } } ``` **Knight.java** ```java import java.util.Random; public class Knight extends Hero { // 생성자 public Knight(String name) { super(name); super.hp += 100; // 체력 +100 } // 배쉬 public void bash(Hero enermy) { enermy.hp -= 30; System.out.printf("[%s]의 ⤷︎ 배쉬 ⤵\n", this.name); System.out.printf("\t%s: %d\n", enermy.name, enermy.hp); } // 공격 @Override public void attack(Hero enermy) { if (new Random().nextBoolean()) this.bash(enermy); else super.attack(enermy); } } ``` **Wizard.java** ```java import java.util.Random; public class Wizard extends Hero { // 생성자 public Wizard(String name) { super(name); super.hp += 80; } // 파이어볼 public void fireball(Hero enermy) { enermy.hp -= 35; System.out.printf("[%s]의 ✡ 파이어볼 ✡\n", this.name); System.out.printf("\t%s: %d\n", enermy.name, enermy.hp); } // 공격 @Override public void attack(Hero enermy) { if (new Random().nextBoolean()) this.fireball(enermy); else super.attack(enermy); } } ``` ### 실행결과 <div class="embed-responsive embed-responsive-4by3"> <iframe class="embed-responsive-item" src="https://www.youtube.com/embed/G2thT593Dpg"></iframe> </div>
# 매출 계산하기 I 손수 적어 정리하던 매출.. 이제는 프로그램을 만들어 해결하기! --- ### 상황설정 라면가게를 오픈한 왕라면(45) 사장님.. 요즘 손님이 부쩍늘어 행복한 고민중이군요. 일일이 적어오던 매출전표도 이제는 도저히 손으로 감당하기가 어려워졌다 합니다.(~~종종 금액이 맞지 않는 경우가 생긴다 하네요~~) ![](https://www.dropbox.com/s/mpjfp5u4lz3rlbv/1301.jpg?dl=1) --- ### 아이디어 컴공과에 재학중인 왕라면 사장님의 아들 왕공돌(21) 학생. 이러한 문제를 해결하기 위해 직접 매출계산 소프트웨어를 만들기도 결심합니다. 주문이 들어오는 대로 바로바로 매출을 기록해주는 소프트웨어를 만들기로 한 것이죠. ![](https://www.dropbox.com/s/0d9qk2bhxwb7z8h/1302.jpg?dl=1) --- ### 메뉴분석 왕라면집 메뉴는 라면과 김밥으로 단 2가지만 있다고 합니다. ![](https://www.dropbox.com/s/6zucjlno6ki560n/1303.jpg?dl=1) --- ### 프로그램 설계 왕공돌 학생은, 프로그램을 구현하기위해 설계를 시작하였습니다. 필요 클래스는 3가지로 정하였으며 역할은 아래와 같습니다. ![](https://www.dropbox.com/s/ske2db48o376no7/1304.jpg?dl=1) + **SalesAnalyzer**(매출 분석기) - 주문이 들어오면 라면, 김밥같은 객체들을 일일히 기록 - 기록된 주문을 토대로 매출을 계산 + **Ramyun**(라면) - 메뉴의 이름과 가격 정보를 지님. + **Kimbob**(김밥) - 메뉴의 이름과 가격 정보를 지님. --- ### 스켈레톤 코드 현재까지 왕공돌 학생이 만든 코드는 아래와 같습니다. **SalesAnalyzer.java** ```java import java.util.ArrayList; import java.util.Random; public class SalesAnalyzer { // 주문 리스트 private ArrayList<Ramyun> ramyunOrders; private ArrayList<Kimbob> kimbobOrders; public SalesAnalyzer() { this.ramyunOrders = new ArrayList<Ramyun>(); this.kimbobOrders = new ArrayList<Kimbob>(); } // 메인 테스트 public static void main(String[] args) { SalesAnalyzer sales = new SalesAnalyzer(); // 랜덤 주문 생성. sales.randomOrders(); // 매출 계산. int totalSales = sales.calculateSales(); System.out.println("총 매출액: " + totalSales + "원"); } // 랜덤 주문 생산기 public void randomOrders() { Random random = new Random(); int n = 51 + random.nextInt(50); for (int i = 0; i < n; i++) { if (random.nextBoolean()) addRamyunOrder(new Ramyun()); else addKimbobOrder(new Kimbob()); } } // 라면 주문 기록 public void addRamyunOrder(Ramyun ramyun) { ramyunOrders.add(ramyun); } // 김밥 주문 기록 public void addKimbobOrder(Kimbob kimbob) { kimbobOrders.add(kimbob); } // 매출 계산 public int calculateSales() { int raCount = 0; int kimCount = 0; int raSales = Ramyun.PRICE * raCount; int kimSales = Kimbob.PRICE * kimCount; int totalSales = 0; System.out.printf("[라면] %d개: %d원\n", raCount, raSales); System.out.printf("[김밥] %d개: %d원\n", kimCount, kimSales); System.out.println("=================="); return totalSales; } } ``` **Ramyun.java** ```java public class Ramyun { public static final String NAME = "라면"; public static final int PRICE = 3000; } ``` **Kimbob.java** ```java public class Kimbob { public static final String NAME = "김밥"; public static int PRICE = 2000; } ``` --- ### 프로그램 구현 이제부터 주어진 소스코드를 분석하고 아래와 같은 결과화면을 얻도록 소스코드를 작성해 봅시다. ![](https://www.dropbox.com/s/h5hhqonb4ob8c4x/1305.png?dl=1) --- ### Next.. 왕라면 사장님께서 메뉴(떡볶이, 튀김, 순대, etc..)를 추가한다고 합니다.
# 매출 계산하기 II 인터페이스를 하용하여 소스코드 구조를 간결하게! --- ### 상황설정 얼마 전 라면가게를 오픈한 왕라면 사장님!! 가게명을 **왕분식**으로 변경후, 다양한 메뉴를 추가하기 시작하는데.. ![](https://www.dropbox.com/s/xr5w0bxj1keek1m/1401.jpg?dl=1) --- ### 복잡해지는 소스코드 이로 인해 매출 계산 프로그램은 확장작업이 필요하게 된다.. ![](https://www.dropbox.com/s/u8gs0txyh4xxjvg/1402.jpg?dl=1) 메뉴가 추가될수록 늘어만 가는 대량의 코드.. 왕공돌(21세; 매출계산 프로그램 개발자) 학생의 고민은 깊어만 가는데.. --- ### 스켈레톤 코드 현재까지 작성된 소스코드는 아래와 같습니다. **SalesAnalyzer.java** ```java import java.util.ArrayList; import java.util.Random; public class SalesAnalyzer { // 주문 리스트 private ArrayList<Ramyun> ramyunOrders; private ArrayList<Kimbob> kimbobOrders; private ArrayList<Topokki> topokkiOrders; private ArrayList<Twigim> twigimOrders; private ArrayList<Sundae> sundaeOrders; private ArrayList<Mandu> manduOrders; private ArrayList<Odeng> odengOrders; public SalesAnalyzer() { this.ramyunOrders = new ArrayList<Ramyun>(); this.kimbobOrders = new ArrayList<Kimbob>(); this.topokkiOrders = new ArrayList<Topokki>(); this.twigimOrders = new ArrayList<Twigim>(); this.sundaeOrders = new ArrayList<Sundae>(); this.manduOrders = new ArrayList<Mandu>(); this.odengOrders = new ArrayList<Odeng>(); } // 메인 테스트 public static void main(String[] args) { SalesAnalyzer sales = new SalesAnalyzer(); // 랜덤 주문 생성. sales.randomOrders(); // 매출 계산. int totalSales = sales.calculateSales(); System.out.println("총 매출액: " + totalSales + "원"); } // 랜덤 주문 생산기 public void randomOrders() { Random random = new Random(); int n = 51 + random.nextInt(50); for (int i = 0; i < n; i++) { switch (random.nextInt(7)) { case 0: addRamyunOrder(new Ramyun()); break; case 1: addKimbobOrder(new Kimbob()); break; case 2: addTopokkiOrder(new Topokki()); break; case 3: addTwgimOrder(new Twigim()); break; case 4: addSundaeOrder(new Sundae()); break; case 5: addManduOrder(new Mandu()); break; case 6: addOdengOrder(new Odeng()); break; } } } // 라면 주문 기록 public void addRamyunOrder(Ramyun ramyun) { ramyunOrders.add(ramyun); } // 김밥 주문 기록 public void addKimbobOrder(Kimbob kimbob) { kimbobOrders.add(kimbob); } // 떡복이 주문 기록 public void addTopokkiOrder(Topokki topokki) { topokkiOrders.add(topokki); } // 튀김 주문 기록 public void addTwgimOrder(Twigim twigim) { twigimOrders.add(twigim); } // 순대 주문 기록 public void addSundaeOrder(Sundae sundae) { sundaeOrders.add(sundae); } // 만두 주문 기록 public void addManduOrder(Mandu mandu) { manduOrders.add(mandu); } // 오뎅 주문 기록 public void addOdengOrder(Odeng odeng) { odengOrders.add(odeng); } // 매출 계산 public int calculateSales() { int raCount = ramyunOrders.size(); int kimCount = kimbobOrders.size(); int toCount = topokkiOrders.size(); int twiCount = twigimOrders.size(); int sunCount = sundaeOrders.size(); int manCount = manduOrders.size(); int oCount = odengOrders.size(); int raSales = Ramyun.PRICE * raCount; int kimSales = Kimbob.PRICE * kimCount; int toSales = Topokki.PRICE * toCount; int sunSales = Sundae.PRICE * sunCount; int twiSales = Twigim.PRICE * twiCount; int manSales = Mandu.PRICE * manCount; int oSales = Odeng.PRICE * oCount; int totalSales = raSales + kimSales + toSales + sunSales + twiSales + manSales + oSales; System.out.printf("[라면] %d개: %d원\n", raCount, raSales); System.out.printf("[김밥] %d개: %d원\n", kimCount, kimSales); System.out.printf("[떡볶이] %d개: %d원\n", toCount, toSales); System.out.printf("[튀김] %d개: %d원\n", twiCount, twiSales); System.out.printf("[순대] %d개: %d원\n", sunCount, sunSales); System.out.printf("[만두] %d개: %d원\n", manCount, manSales); System.out.printf("[오뎅] %d개: %d원\n", oCount, oSales); System.out.println("=================="); return totalSales; } } ``` **Ramyun.java** ```java public class Ramyun { public static final String NAME = "라면"; public static final int PRICE = 3000; } ``` **Kimbob.java** ```java public class Kimbob { public static final String NAME = "김밥"; public static int PRICE = 2000; } ``` **Topokki.java** ```java public class Topokki { public static final String NAME = "떡볶이"; public static int PRICE = 2000; } ``` **Twigim.java** ```java public class Twigim { public static final String NAME = "튀김"; public static int PRICE = 2000; } ``` **Sundae.java** ```java public class Sundae { public static final String NAME = "순대"; public static int PRICE = 2000; } ``` **Mandu.java** ```java public class Mandu { public static final String NAME = "만두"; public static int PRICE = 2500; } ``` **Odeng.java** ```java public class Odeng { public static final String NAME = "오뎅"; public static int PRICE = 2500; } ``` **실행결과** ![](https://www.dropbox.com/s/6rt57l5d9z942zi/1403.png?dl=1)
# 매출 계산하기 III --- ### 자바 인터페이스 메뉴의 추가로 인해 거대해진 `SalesAnalyzer`클래스.. 왕공돌 학생은 이를 해결하기 위해 교수님께 조언을 구한다.. ![](https://www.dropbox.com/s/3zf1qo42f4v9w23/1404.jpg?dl=1) 교수님 왈, ![](https://www.dropbox.com/s/7zfbv8ndbc0gbyh/1405.jpg?dl=1) 이에 따라, 왕공돌 학생은 인터페이스에 대해 조사를 하게되고.. 기존 소스코드에 인터페이스를 적용하기로 한다. > **자바 인터페이스** > 같은 기능을 하는 클래스들을 하나로 묶어 관리할 수 있게 해준다 --- ### 인터페이스 생성과 구현 먼저 인터페이스를 추가해주는 왕공돌 학생. **menu.java** ```java public interface Menu { public String getName(); public int getPrice(); } ``` 다음으로 각각의 메뉴객체(라면, 김밥, ...)들에게 인터페이스를 구현하도록 해주었군요. **Ramyun.java** ```java public class Ramyun implements Menu { public static final String NAME = "라면"; public static final int PRICE = 3000; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` **Kimbob.java** ```java public class Kimbob implements Menu { public static final String NAME = "김밥"; public static int PRICE = 2000; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` **Topokki.java** ```java public class Topokki implements Menu { public static final String NAME = "떡볶이"; public static int PRICE = 2000; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` **Twigim.java** ```java public class Twigim implements Menu { public static final String NAME = "튀김"; public static int PRICE = 2000; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` **Sundae.java** ```java public class Sundae implements Menu { public static final String NAME = "순대"; public static int PRICE = 2000; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` **Mandu.java** ```java public class Mandu implements Menu { public static final String NAME = "만두"; public static int PRICE = 2500; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` **Odeng.java** ```java public class Odeng implements Menu { public static final String NAME = "오뎅"; public static int PRICE = 2500; @Override public String getName() { return NAME; } @Override public int getPrice() { return PRICE; } } ``` --- ### 리팩토링 하기 인터페이스의 모든 구현을 마친 왕공돌 학생. 이제 최종 보스인 `SalesAnalyzer`클래스를 리팩토링 하기 시작하는데.. > **리팩토링이란?** > 결과의 변동 없이, 소스코드의 구조를 효율적으로 변경하는 작업 ```java import java.util.ArrayList; import java.util.Random; public class SalesAnalyzer { // 주문 리스트 private ArrayList<Menu> orders; public SalesAnalyzer() { orders = new ArrayList<Menu>(); } // 메인 테스트 public static void main(String[] args) { SalesAnalyzer sales = new SalesAnalyzer(); // 랜덤 주문 생성. sales.randomOrders(); // 매출 계산. int totalSales = sales.calculateSales(); System.out.println("총 매출액: " + totalSales + "원"); } // 랜덤 주문 생산기 public void randomOrders() { Random random = new Random(); int n = 51 + random.nextInt(50); for (int i = 0; i < n; i++) { orders.add(randomOrder()); } } private Menu randomOrder() { Menu menu = null; Random random = new Random(); switch (random.nextInt(7)) { case 0: menu = new Ramyun(); break; case 1: menu = new Kimbob(); break; case 2: menu = new Topokki(); break; case 3: menu = new Twigim(); break; case 4: menu = new Sundae(); break; case 5: menu = new Mandu(); break; case 6: menu = new Odeng(); break; } return menu; } // 매출 계산 public int calculateSales() { int totalSales = 0; int raCount = 0; int kimCount = 0; int toCount = 0; int twiCount = 0; int sunCount = 0; int manCount = 0; int oCount = 0; for (Menu menu : orders) { if (menu.getClass() == Ramyun.class) raCount++; else if (menu.getClass() == Kimbob.class) kimCount++; else if (menu.getClass() == Topokki.class) toCount++; else if (menu.getClass() == Twigim.class) twiCount++; else if (menu.getClass() == Sundae.class) sunCount++; else if (menu.getClass() == Mandu.class) manCount++; else if (menu.getClass() == Odeng.class) oCount++; totalSales += menu.getPrice(); } int raSales = Ramyun.PRICE * raCount; int kimSales = Kimbob.PRICE * kimCount; int toSales = Topokki.PRICE * toCount; int sunSales = Sundae.PRICE * sunCount; int twiSales = Twigim.PRICE * twiCount; int manSales = Mandu.PRICE * manCount; int oSales = Odeng.PRICE * oCount; System.out.printf("[라면] %d개: %d원\n", raCount, raSales); System.out.printf("[김밥] %d개: %d원\n", kimCount, kimSales); System.out.printf("[떡볶이] %d개: %d원\n", toCount, toSales); System.out.printf("[튀김] %d개: %d원\n", twiCount, twiSales); System.out.printf("[순대] %d개: %d원\n", sunCount, sunSales); System.out.printf("[만두] %d개: %d원\n", manCount, manSales); System.out.printf("[오뎅] %d개: %d원\n", oCount, oSales); System.out.println("=================="); return totalSales; } } ``` --- ### 최종결과 훗날 왕공돌 학생은 추가되는 메뉴에도 손쉽게 프로그램을 확장할 수 있었다고 한다.. ![](https://www.dropbox.com/s/1399f693wvbr0fz/1406.png?dl=1)