티스토리 뷰
이번주에는 자바의 정석 객체지향 부분을 집중적으로 공부하고 코딩해보았습니다.
먼저 객체지향에 대해서 요약하자면
객체지향 프로그래밍은 데이터와 기능을 하나의 단위인 객체로 묶어서 처리하는 프로그래밍 방식이다.
캡슐화, 상속, 다형성 등의 개념이 중요하고 코드의 재사용성과 유연성을 높인다.
객체 지향적인 설계 방식은 프로그래밍의 복잡도를 낮추고 유지보수성을 향상시키는데 도움이 된다.
그래서 나는 객체지향에서 중요한 캡슐화, 추상화, 상속, 다형성 개념을
적용하면서 공부하고 과제에도 최대한 적용해보려고 했습니다.
밑에 있는 코드는 과제에있는 버스 작동 코드입니다.
내가 구현하고 싶은 기능입니다. 버스상태, 기름감소, 승객탑승 기능을 인터페이스로 작성
package SA;
public interface BusFunction {
void busState(String str);
void gasDecrease(int num);
void addPassenger(int num);
}
인터페이스를 상속받고 캡슐화를 위해 변수들을 외부에서 직접 접근 못하도록 getter, setter 적용
package SA;
abstract class Bus implements BusFunction {
private int maxPassenger;
private int passenger;
private int fare;
private int busNumber;
private int fuelLevel;
private int speed;
private String state;
public Bus(int maxPassenger, int fare, int busNumber, int speed) {
this.maxPassenger = maxPassenger;
this.passenger = 0;
this.fare = fare;
this.busNumber = busNumber;
this.fuelLevel = 100;
this.speed = speed;
this.state = "운행중";
System.out.println("버스번호 " + busNumber + "번 생성되었습니다.");
System.out.println("탑승가능 총원은 " + maxPassenger + "명, 요금은 " + fare + "원 입니다.");
}
public int getMaxPassenger() {
return maxPassenger;
}
public void setMaxPassenger(int maxPassenger) {
this.maxPassenger = maxPassenger;
}
public int getPassenger() {
return passenger;
}
public void setPassenger(int passenger) {
this.passenger = passenger;
}
public int getFare() {
return fare;
}
public void setFare(int fare) {
this.fare = fare;
}
public int getBusNumber() {
return busNumber;
}
public void setBusNumber(int busNumber) {
this.busNumber = busNumber;
}
public int getFuelLevel() {
return fuelLevel;
}
public void setFuelLevel(int fuelLevel) {
this.fuelLevel = fuelLevel;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Bus 추상메서드를 상속 받고 인터페이스 기능들을 구현했습니다.
package SA;
public class BusController extends Bus {
public BusController(int maxPassenger, int fare, int busNumber, int speed) {
super(maxPassenger, fare, busNumber, speed);
}
@Override
public void busState(String str) {
if (str.equals("차고지행")) {
setState("차고지행");
setPassenger(0);
} else setState("운행중");
System.out.println("상태 = " + getState());
}
@Override
public void gasDecrease(int num) {
int nowgas = getFuelLevel();
if ((getFuelLevel() + num) < 10) {
setState("차고지행");
setFuelLevel(nowgas + num);
System.out.println("현재 주유량 = " + getFuelLevel());
System.out.println("상태 = " + getState());
System.out.println("주유필요");
} else {
setFuelLevel(nowgas + num);
System.out.println("현재 주유량 = " + getFuelLevel());
}
}
@Override
public void addPassenger(int num) {
if (num > getMaxPassenger()) System.out.println("최대 승객 수 초과");
else {
setPassenger(getPassenger() + num);
System.out.println("탑승 승객 수 = " + getPassenger());
int maxnum = getMaxPassenger();
int nownum = getPassenger();
System.out.println("잔여 승객 수 = " + (maxnum - nownum));
int fare = getFare();
System.out.println("요금 확인 = " + (fare * num));
}
}
}
단일 책임 원칙 (Single Responsibility Principle, SRP) 하나의 클래스는 하나의 책임만 가지며, 클래스가 변경되어야 하는 이유도 하나여야 한다는 원칙입니다. SRP를 지키면 클래스 간의 결합도를 낮출 수 있으며, 유지보수성과 확장성을 높일 수 있습니다.
개방-폐쇄 원칙 (Open-Closed Principle, OCP) 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계되어야 한다는 원칙입니다. 새로운 기능이 추가될 때 기존 코드를 수정하는 것이 아니라, 확장을 통해 기능을 추가할 수 있도록 설계해야 합니다.
리스코프 치환 원칙 (Liskov Substitution Principle, LSP) 자식 클래스는 언제나 부모 클래스의 자리를 대체할 수 있어야 한다는 원칙입니다. LSP를 지키면 상속 관계에서의 호환성을 보장할 수 있습니다.
인터페이스 분리 원칙 (Interface Segregation Principle, ISP) 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다는 원칙입니다. ISP를 지키면 불필요한 의존 관계를 제거하여 결합도를 낮출 수 있으며, 인터페이스의 재사용성을 높일 수 있습니다.
의존관계 역전 원칙 (Dependency Inversion Principle, DIP) 추상화에 의존해야 하며, 구체화에 의존하면 안 된다는 원칙입니다. DIP를 지키면 코드의 유연성과 재사용성을 높일 수 있으며, 의존성 주입(Dependency Injection)을 통해 불필요한 의존 관계를 제거할 수 있습니다.
바로 위의 내용은 객체지향 설계원칙인 SOLID 이다. 과제를 하면서 객체지향 설계원칙인 SOLID를 적용하고 싶었는데 아직 이 개념이 이해가 완전하지 못했고 막연하게 머리로 생각하고 코드를 작성하다 보니 설계를 어떻게 해야하지? 라는 의문이 많이 들었고 방법이 많이 부족해서 구현 능력이 많이 부족하다고 느꼈다.
JVM 에 대해서도 알아보았는데 JVM은 자바 바이트코드를 실행시키기 위한 가상머신이다.
JVM만 설치되어 있다면 어떤 운영체제에서도 실행이 가능하다. JVM을 통해서 운영체제와 상관없이 동일한 실행 결과가 나온다.
minor version: 0
major version: 58
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #17 // Wonit
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
public class Wonit
minor version: 0
major version: 58
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
... 생략
#24 = Utf8 Wonit.java
{
public Wonit();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
Code:
stack=4, locals=4, args_size=1
0: ldc #7 // String 워닉
5: istore_2
... 생략
20: return
LineNumberTable:
line 3: 0
line 4: 3
line 6: 6
line 8: 16
line 9: 20
}
SourceFile: "Wonit.java"
그리고 자바는 가비지 컬렉션을 통해서 사용하지 않는 객체를 자동으로 제거한다.
그래서 개발자가 메모리를 관리하는 것에 비해 안정성이 높고 생산성을 높일 수 있다고 한다.
참고사이트
[조금 더 깊은 Java] Java Bytecode 를 알아보자 (자바를 컴파일하면 어떤 일이 일어날까?)
우리는 많은 시간 Java를 이용해서 다양한 소프트웨어를 개발하면서 들었던 소리가 있다. Java는 JVM 이 있기 때문에 플랫폼에 종속적이지 않고 이식성이 뛰어나다. 그 이유에 대해서 생각해본 경
wonit.tistory.com
'Spring' 카테고리의 다른 글
@Valid 어노테이션으로 Parameter 검증하기 ft.정규식 (0) | 2023.03.05 |
---|---|
JPA (0) | 2023.03.04 |
트랜젝션(Transaction) (0) | 2023.03.02 |
IoC 와 DI (0) | 2023.03.01 |
Spring MVC 패턴 CRUD API 만들기 (0) | 2023.02.28 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 시작 템플릿
- aws
- script
- JWT
- 로드 밸런서
- Auto Scaling
- githubactions
- Load Balancer
- CICD
- HTML
- 오토 스케일링
- 위치의 중요성
- flask
- java
- CodeDeploy
- 로드밸런서
- 인스턴스
- EC2
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함