객체지향의 4대 특성인 캡슐화, 상속, 추상화, 다형성 을 이용하여 객체 지향을 올바르게 설계할 수 있도록 도와주는 원칙
객체 지향을 공부해봤고, 객체 지향으로 향 후 프로그래밍을 하려면 반드시 알아야 하는 중요한 원칙들이어서. 굉장히 중요하기 때문에 하나하나 원칙들을 정리해봤다.
아무리 객체 지향 4대 특성인 캡슐화, 상속, 추상화, 다형성을 잘한다고 해서 설계를 잘하는 것은 아니다. 물론 4대 특성의 묘미를 잘 살릴수록 설계가 좋다. 하지만 설계 원칙이라는 게 엄연히 존재하고, 또 나름 중요하기 때문에 각 원칙의 맨 앞 알파벳만 따와 "SOLID"라고까지 했을까? SOLID 원칙들은 결국 자기 자신 클래스 안에 응집도는 내부적으로 높이고, 타 클래스들 간 결합도는 낮추는 High Cohesion - Loose Coupling 원칙을 객체 지향의 관점에서 도입한 것이다. 왜 그랬을까? 간단하다. 좋은 소프트웨어는 응집도가 높고 결합도가 낮기 때문이다. 결국 모듈 또는 클래스 당 하나의 책임을 주어 더욱더 독립된 모듈(클래스)을 만들기 위함이다. 이렇게 설계된 소프트웨어는 재 사용이 많아지고, 수정이 최소화되기 때문에 결국 유지 보수가 용이해진다.
1) SRP (Single Responsibility Principle) 단일 책임 원칙
-> 클래스의 역할과 책임을 너무 많이 주지 마라.
2) OCP (Open Closed Principle) 개방 폐쇄 원칙
-> 자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야 한다.
3) LSP (Liskov Substitution Principle) 리스코프 치환 원칙
-> 인터페이스와 클래스 관계, 상위 클래스와 하위 클래스 관계를 얼마나 잘 논리적으로 설계했느냐가 관건이다. 인터페이스는 위와 같이 ~able을 붙여서 네이밍하고 인터페이스를 implements 한 구현 클래스는 인터페이스가 가지고 있는 기능을 할 수 있다로 생각하면 된다.
4) ISP (Interface Segregation Principle) 인터페이스 분리 원칙
-> 상황과 관련 있는 메서드만 제공해라.
5) DIP (Dependency Inversion Principle) 의존 역전 원칙
-> 자신보다 변하기 쉬운 것에 의존하지 마라.
< public, protected, default, private >
public : 외부 클래스가 자유롭게 접근이 가능하다.
protected : 같은 패키지이거나 자식 클래스에서 접근이 가능하다.
default : 같은 패키지에 소속된 클래스에서만 접근이 가능하다.
private : 선언한 클래스 내부에서만 접근이 가능하다.
접근의 개방 정도는 public > protected > default > private 순으로 열려있다고 보면 된다.
여기서 default 접근 제한은 public, protected, private을 모두 생략한 상태가 default이다.
< Static, Final >
Final : 특정한 어떠한 값이 변경되지 않아야 할 때 사용한다. final 변수의 경우 수정할 수 없지만, final 객체의 경우 수정이 가능하다. 예로
- final의 메서드인 경우에도 Override가 되지 않는다.
- final의 클래스인 경우에 클래스 자체 상속을 불가하게 만든다.
객체인 ArrayList의 경우 final List는 ArrayList의 값을 가지고 있는 것이 아니고, ArrayList 객체의 주소를 참조하고 있기 때문이다.
ex)
final ArrayList<String> List = new ArrayList <String>();
List.add("A");
List.add("B");
List.add("C");
Static : 메모리에 바로 올라가며, 아무 곳에서나 호출이 가능하다. static이 붙은 변수는 클래스의 모든 객체가 공유할 수 있다고 해서 클래스 변수라고도 불린다. 또한 클래스의 객체 생성 없이 호출하여 사용할 수 있다는 장점이 있는데, 다른 클래스에서 접근하려는 경우 static 변수가 존재하는 클래스 명 뒤에 점 (.)을 찍고 static 변수의 명을 써주면 접근이 가능하다.
또한 static이 선언된 메서드는 오버라이딩 되지 않고 메서드 숨김이 일어나 상속받은 클래스에서 사용이 불가하다.
static은 전역적으로 쉽게 재사용하는 멤버나 잘 변하지 않는 변수나, 메서드를 사용할 때 주로 사용된다. 만들어 놓고 클래스 호출, 객체 생성을 따로 할 필요 없이 바로바로 사용할 수 있기 때문에 사용성이 좋다. 하지만 static은 메모리 자원을 할당해놓고 사용하는 것이기 때문에 너무 많이 사용한다면 메모리를 많이 차지하게 되어서 프로그램이 무거워진다.
< 생성자(Constructor) >
생성자는 new 연산자를 통해서 인스턴스를 생성할 때 반드시 호출이 되고 제일 먼저 실행되는 일종의 메소드이다. (하지만 메소드와는 다르다.) 생성자는 인스턴스 변수(필드 값 등)를 초기화 시키는 역할을 한다. 추가로 생성자의 매개변수를 다르게 지정하여 정의하는 것을 생성자 오버로딩이라고 한다. 생성자와 메소드의 차이로 생성자는 반드시 클래스명과 동일하게 정의하여야 하며, 생성자 앞에는 접근 제어자(public 등)만 올 수 있다. (메소드는 static과 같은 수식어를 작성할 수 있다.) 또한 반환값이 없으므로 void나 자료형을 작성할 수 없고, 그 외에도 상속이 되지 않는 차이가 있다.
'Spring & Java > Programming' 카테고리의 다른 글
6. 핵심원리 기본편 (0) | 2022.08.02 |
---|---|
5. 개념 (0) | 2022.07.18 |
4. 스프링 웹 개발 기초 (0) | 2022.07.14 |
3. Java (TDD, GCC) (0) | 2022.07.14 |
1. Java (0) | 2022.07.13 |