반응형

본 글은 책 자바의 정석을 ref 하여 요약한 글입니다.


 

책의 내용은 아니지만 가장 먼저 절차적 프로그래밍과 객체지향 프로그래밍의 차이를 비교하고자 한다.

절차적 프로그래밍의 경우 공유 데이터 하나를 여러 함수를 통해서 조작하게 된다.

객체지향 프로그래밍에서는 객체는 자신의 데이터(상태)를 갖고 있고 이를 메서드를 통해 다른 객체와 상호작용한다.

데이터를 어떻게 다루냐에 있어서 차이가 있다.

 

절차적 프로그래밍 - 데이터, 함수가 분리

객체지향 프로그래밍 - 데이터, 함수가 결합

 


 

클래스와 객체

클래스 - 설계도, 데이터와 함수의 결합

객체 - 설계도에 따라 heap 영역에 인스턴스가 생성된 상태

* 자신을 참조하는 참조 변수가 없는 경우 인스턴스는 garbage collector에 의해 메모리에서 제거된다.

 

구성요소

속성 - 객체의 상태 값

기능 - 메서드

 

변수

클래스 변수 - 클래스가 메모리에 올라갈 때 생성

인스턴스 변수 - 인스턴스가 생성되면 생성

지역 변수 - 메서드가 호출되면 생성되었다가 메서드가 종료되면 소멸

 

메서드 

중복된 코드를 재사용하며 구조화

인자로 주거나 결괏값을 받을 때 자동 형 변환이 되는 type으로 지정, 안된다면 형 변환 후 넘긴다.

 

JVM 메모리 구조

메서드 영역 - 클래스 변수, 클래스 정보

힙 영역 - 생성된 인스턴스 

스택 영역 - 메서드(stack frame) 스택에 생성되고 처리 후 비운다.

 

기본형 매개변수와 참조형 매개변수

자바는 call by reference가 없다. 전부 call by value이며, 참조형 매개변수는 메모리의 주소가 아닌 객체 참조값을 넘긴다.

 

클래스(static) 메서드

인스턴스를 생성하지 않아도 사용 가능

클래스 메서드에는 인스턴스 변수를 사용할 수 없다. (클래스 메서드가 먼저 메모리에 올라감)

 

오버 로딩

같은 이름의 메서드명으로 인자의 type, 개수를 다르게 하여 여러 개의 메서드를 정의(리턴 타입은 영향 없다)

 

오버 라이딩

부모에게 상속받은 메서드를 재정의하여 사용한다.

이름, 매개변수, 리턴 타입이 같아야 한다.

 

생성자

객체의 인스턴스 변수를 초기화한다.

클래스의 이름과 같아야 한다.

기본 생성자는 컴파일러가 추가한다. 생성자를 하나라도 정의했다면 개발자가 기본 생성자를 작성해주어야 한다.

this() - 생성자 내부에서 다른 생성자를 호출한다. 가장 첫 줄에 작성한다.

 


 

상속

부모의 생성자, 초기화 블록을 제외한 멤버(속성, 기능)를 물려받는다.

** private로 선언된 멤버는 상속되지 않는다.  (super로 접근하여 사용한다.)

** 부모 자식 클래스가 다른 패키지라면 default로 선언된 멤버는 상속되지 않는다.

** 자식 클래스 내부 - super.getter, super.setter || 외부 - getter, setter 

자바에서는 단일 상속만을 허용한다.

 

클래스 간의 관계

포함관계 (has) - 상속하여 사용하지 않고, 속성에 다른 객체를 포함하여 해당 객체의 멤버를 사용한다.

상속관계 (is) - 상속관계라고 하지만 소속 관계라고 이해하고 있다.

 

super

부모, 자식과의 변수명이 같을 때 super, this를 이용해서 구분해줄 수 있다.

변수뿐만 아니라 오버 라이딩한 메서드의 구분도 가능하다.

super() - 부모 생성자를 호출하여 상속받은 부모 속성을 초기화할 수 있다. this()와 마찬가지로 가장 첫 줄에 위치한다. 

 


 

패키지

클래스들의 묶음

클래스의 실제 이름은 패키지명을 포함

클래스 파일을 압축한 것이 jar

 

import

패키지가 다른 클래스를 사용할 때 패키 지명이 포함된 클래스를 작성하는 것이 불편해서 import를 이용한다.

import를 하게 되면 클래스명 만으로 사용 가능하다.

 

제어자

static - 클래스가 메서드 영역에 로드될 때 같이 로드된다. (속성, 메서드)

final - 변경될 수 없다는 의미 (클래스, 메서드, 변수)

abstract - 미완성의 의미 (클래스, 메서드)

 

접근제어자

public - 제한 없음

protected - 다른 패키지여도 상속한다면 사용이 가능하다. (클래스가 public 이어야 상속 후 protected 멤버 사용 가능)

default - 같은 패키지

private - 같은 클래스

 


 

다형성

하나의 참조타입로 여러 타입의 인스턴스를 사용 (클래스, 추상 클래스, 인터페이스)

업 캐스팅시 자식의 멤버는 사용할 수 없다. 오버 라이딩된 메서드는 사용 가능

참조 타입이 바뀌더라도 인스턴스는 바뀌지 않는다. (멤버 사용 범위가 달라질 뿐)

instanceof - 인스턴스를 이용해서 참조 타입으로 변환할 수 있는지 확인한다.

ex) 참조 변수(인스턴스) instanceof 참조 타입

 

다형성의 주의점

** 메서드를 오버 라이딩했다면 항상 자손의 오버 라이딩 메서드를 사용한다.

** 부모 메서드의 접근 제한자보다 오버 라이딩한 자식 메서드를 더 강한 접근 제한자를 설정할 수 없다.

** 오버 라이딩 메서드 내부에서 자신의 속성을 사용할 수 있다. (this)

** 같은 이름의 속성은 참조 타입에 의존한다.

 


 

추상 클래스

클래스들의 공통부분을 추상화해놓는다.

추상 클래스는 추상 메서드를 갖는다.

생성자를 가질 수 있다.

인스턴스를 생성할 수 없다.

* 동작이 동일한 부분은 일반 메서드로 구현해놓는다.

* 공통 부분이지만 인스턴스에 따라 달라지는 메서드는 추상 메서드로 선언한다.

 

인터페이스

추상 메서드와 상수만을 가질 수 있다. (static, default 메서드를 가질 수 있지만 복잡성을 줄이기 위해 일단 이렇게 이해)

 


 

** 추상 클래스와 인터페이스의 차이

추상 클래스는 클래스의 상속(소속) 관점 - (공통 기능을 구현해줄 수 있다.)

인터페이스는 단순히 기능 관점 - (필요 기능을 명시해줄 수 있다.)

 

추상 클래스는 재사용성의 관점에서 유용

인터페이스는 교체의 관점 유용

 

(추상클래스) 동물 - 사자, 독수리  소속 관점

(인터페이스) 독수리와 벌의 flyable  기능 관점(소속이 달라도 기능이 같다.)

 

추상 클래스는 상태 변수 필드를 갖고 있다.

인터페이스는 상태 값을 갖지 못하고 상수만 갖고 있다.

 

 

** 인터페이스의 이해

사용부(클라이언트 코드)에서는 내부를 알 필요가 없다. 메서드만 알면 된다.

인스턴스가 변경되더라도 메서드명은 같다. 유지보수가 편하다.

 


 

내부 클래스

가장 먼저 외부 클래스는 프로그램이 실행되면 메서드 영역에 올라간다는 점을 알면 이해하기 편하다.

* static이 인스턴스보다 먼저 로드된다.

 

인스턴스 클래스 - 외부 클래스 인스턴스가 생성되어야 사용 가능, 외부 클래스의 private 멤버도 접근 가능

스태틱 클래스 - 외부 클래스 인스턴스가 생성되지 않아도 사용 가능, 인스턴스 멤버에 접근 불가(static은 먼저 로드되기 때문)

지역 클래스 - 메서드가 종료되면 메서드 내부 지역변수지역 클래스가 알 수 없으므로 상수만 사용 가능하다. (지역 변수는 소멸될 가능성)

 

익명 클래스

하나의 객체만을 생성하는 일회용 클래스, 생성된 객체는 계속 사용할 수 있다. 설계도가 1회성

클래스를 상속받거나 인터페이스를 구현하여 사용한다.

람다식에 유용하게 사용된다.

 

 


 

 

 

 

 

 

 

 

 

반응형
반응형

[학습일지] Java & SpringBoot로 시작하는 웹 프로그래밍 : 자바 인강 7주차


 

7주차 학습내용

 

객체지향

디자인 패턴

 


객체지향

 

현실에 존재하는 물체를 모델링하기 위한 방법론이다.

절차 지향적인 프로그래밍 방법을 객체지향적인 프로그래밍 방법으로 발전시켰다.

 

물체를 객체로 정의하기 위해 해당 객체가 가지고 있는 특성을 분석하여

속성(변수)과 기능(메서드)으로 분리하여 모델링한다.

객체는 실체화된 개념일 수 있고, 추상적인 개념일 수도 있다.

 

상태 유지(속성)

객체는 해당 상태를 저장할 수 있어야 하고 그 상태를 유지해야 한다.

기능 제공(메서드)

객체는 다른 객체와 협력하기 위해 기능을 제공해야 한다.

고유 식별자

객체는 고유한 값을 갖고, 다른 객체와 식별될 수 있어야 한다.

 


 

객체지향의 4대 특성

 

캡슐화

객체의 상태인 속성은 기능을 통해 변경되어야 한다.

무의미한 값을 저장하지 않도록 무결성을 유지할 수 있다.

상속

객체를 구조화할 수 있다. 유지보수가 향상된다.

추상화

객체 간의 특성을 추출하여 추상화시킬 수 있다.

다형성

하나의 인스턴스가 여러 형태로 변화할 수 있다.

코드의 재사용성이 향상된다.

 


 

객체지향 설계의 5원칙(SOLID)

 

객체 간의 의존성은 낮추고, 책임지고 있는 기능에 집중해야 한다.

결합도는 낮추고, 응집도는 높인다.

 

단일 책임 원칙

하나의 객체가 여러 기능을 부담하지 않고, 객체가 하나의 기능에 집중하도록 분리해야 한다.

 

개방 폐쇄 원칙

변경되어야 하는 부분은 폐쇄적이어야 하고, 확장에는 개방되어야 한다.

인터페이스를 사용하면 손쉬운 확장이 가능하고, 클라이언트 코드의 변경도 없다.

 

리스 코프 치환 원칙

부모의 인스턴스가 사용되던 자리에 자식의 인스턴스가 사용된다면

기존의 부모 인스턴스가 갖고 있던 규칙을 자식이 위반하면 안된다. (오버라이딩시 위배가능성)

 

인터페이스 분리 원칙

인터페이스의 기능들을 하나의 인터페이스에 통합하지말고

인터페이스를 분리해서 구현체가 필요한 메서드를 가진 인터페이스만을 구현받도록 분리해야 한다.

 

의존 역전 원칙

의존 객체를 구체적인 구현체가 아닌 상위 추상적인 개념을 의존하게끔 설계해야한다.

 

 


디자인 패턴

 

싱글톤

 

 

생성자를 private로 만들어서 생성할 수 없게 한다.

싱글톤 패턴은 자기 자신을 속성으로 갖고 있다. getInstance 메서드를 통해 자기 자신인 속성을 가져온다.

getInstance가 static이므로 getInstance에서 이용해야 하는 자기 자신인 속성도 static으로 선언된다.

 


 

어댑터

 

 

관련이 없는 두 인터페이스를 중간에서 어댑터가 바꿔치기하여 연결시켜주는 디자인 패턴이다.

기존 인터페이스가 A이고, A 인터페이스를 사용하는 위주로 클라이언트 코드가 작성되었다고 할 때

B 인터페이스 새로 사용해야 한다면 B 인터페이스를 A 인터페이스로 중간에서 교체하는 어댑터를 만들어 줄 수 있다.

 

어댑터는 A 인터페이스를 구현하고, B 인터페이스를 속성으로 받아

A 인터페이스들의 메서드를 호출하면, A메서드를 오버라이딩해서 B 인터페이스 메서드를 대신해서 호출시켜주면 된다.

 


 

프록시

 

 

스프링 프레임워크에서 AOP로 프록시 패턴을 사용한다.

프록시가 인터페이스인 GameInterface를 구현하고, 실제 구현체인 GameService를 속성으로 갖는다.

 

클라이언트 코드에서 직접 GameService를 사용하지 않고 Proxy를 통해 사용한다.

Proxy는 GameService의 메서드를 호출을 하는데, 이때 앞과 뒤로 추가적인 작업이 가능해진다.

 


 

데코레이터

 

상속관계를 통해 super키워드를 이용하여 부모의 메서드를 호출하여

실행 결과를 반환받는 디자인 패턴이다.

 

호출은 (자식 -> 부모) 순으로 호출되며

실행은 (부모 -> 자식)으로 나오게 된다.

 

 


 

옵저버

 

 

변화가 일어날 때 등록해둔 옵저버(인스턴스)들에게 모두 알려주는 것이다.

옵저버를 등록시키고, 특정 함수가 동작할 때 옵저버의 기능이 동작하도록 한다.

 


 

파사드

 

클라이언트 코드가 복잡한 (여러 클래스)들의 기능을 일련의 과정으로 사용할 때

(클라이언트 코드)와 (여러 클래스) 사이에 (파사드 객체)를 두어

파사드 객체가 각 클래스들이 복잡하게 호출되는 일련의 과정을 메서드로 제공한다.

 

클라이언트 코드는 파사드 객체가 제공하는 간단한 메서드를 사용하게 하는 방식이다.

 


 

전략

 

가장 보편적으로 사용되는 패턴으로 

클라이언트 코드단에서 인터페이스를 구현한 구현체 부분을 전략으로 선택하여

선택한 전략 구현체를 사용하는 방법이다.

 

생성자를 인수를 인터페이스로 지정하여 내부 동작들은 인터페이스의 메서드를 사용하여구현체인 인스턴스의 메서드로 동작시키는 것

 

 


 

반응형

+ Recent posts