본문 바로가기

백앤드 개발/Java & Spring

[Java] 컬렉션 프레임워크 실습

1. 싱글톤 패턴이란?

객체의 인스턴스가 오직 1개만 생성되는 패턴

고정된 메모리 영역을 사용하기 때문에 일종의 데이터 베이스 역할 수행

public class Singleton {

    // 정적필드
    private static Singleton instance = new Singleton();

    // 생성자: private으로 외부에서 생성하지 못하도록 선언
    private Singleton() { }

    // 유일한 인스턴스에 접근할 수 있는 정적 메서드
    public static Singleton getInstance() {
        return instance;
    }
}

 

2. 실습 목표

1) 국가데이터 / 산업데이터 가져오는 기능을 구현

2) 국가데이터와 산업 데이터가 담긴 DB역할의 Repository 객체 구현

3) 데이터 처리 코드가 담긴 Service 객체 구현

3. 구조

 

1) repository 패키지: DB 역할을 수행하는 클래스와 인터페이스가 담김

- CallDataRepository 인터페이스: 두 가지 기능을 명시한 인터페이스

- DataRepository 클래스: 싱글톤 객체를 선언해 가상의 DB 역할 수행. 필드가 담겨있고 생성자를 통해 필드에 값이 담김.

- CallDataRepositoryImpl 클래스: 인터페이스를 상속받아 기능 두 가지를 오버라이딩하고 DB 클래스를 선언.

 

2) service  패키지: 업무적인 데이터 처리 작업 구현하는 클래스가 담김

- CallDataService 인터페이스: 데이터 처리 기능 명시

- CallDataServiceImpl 클래스: DB 역할을 하는 객체인 CallDataRepositoryImpl 를 싱글톤 패턴으로 가져옴. 인터페이스를 상속받아 기능 두 가지를 오버라이딩.

 

3) main 패키지: 메인 메소드가 돌아가는 패키지

- MainMethod 클래스

 

4. Repository 패키지 구현

1) CallDataRepository 인터페이스 정의

package lec14.collectionframework.samplecode08.repository;

// 2가지 기능 목록이 정의된 인터페이스 선언
public interface CallDataRepository {
	
	// 국가 이름으로 국가 데이터로 가져오기
	public Object getNationData(String nationName);
	
	// 인덱스로 산업 데이터 가져오기
	public String getIndustryData(int paramIndex);
}

두 가지 기능을 가진  인터페이스를 정의

CallDataRepositoryImpl  를 통해 인터페이스 내 메서드를 정의

 

 

2) DataRepository 클래스 정의 (싱글톤, 가상의 DB 역할)

package lec14.collectionframework.samplecode08.repository.impl;

import java.util.ArrayList;
import java.util.LinkedHashMap;

// 가상의 데이터베이스 역할의 클래스
public class DataRepository {
	
    // 정적 필드
	private static DataRepository instance = new DataRepository();
    
    // 정적 메서드
    // 싱글톤에서 유일하게 외부에서 객체를 얻는 방법
    // 여러 변수들이 동일한 객체를 참고하게 함
	public static DataRepository getInstance() {
		return instance;
	}
	
	// static 으로 안한 이유: 하나의 객체에서 이 데이터에 접근해 사용하기 때문에 (싱글톤 패턴이기 때문에)
	public LinkedHashMap<String, Object> savedDataLkMap = null;
	public ArrayList<String> savedDataArrList = null;
	
	// 생성자
	// 생성자란? 인스턴스가 생성될 때 호출되는 초기화 메서드
    // 생성자의 경우 외부에서 호출되지 못하도록 Private으로 지정
	private DataRepository(){
		
		System.out.println("DataRepository 생성자");
		
		savedDataLkMap = new LinkedHashMap<String, Object>();
		savedDataArrList = new ArrayList<String>();
		
		savedDataLkMap.put("국가1", "한국");
		savedDataLkMap.put("국가2", "미국");
		savedDataLkMap.put("국가3", "중국");
		savedDataLkMap.put("국가4", "일본");
		savedDataLkMap.put("국가5", "러시아");
		
		savedDataArrList.add("전기");
		savedDataArrList.add("자동차");
		savedDataArrList.add("조선");
		savedDataArrList.add("IT");
		savedDataArrList.add("디스플레이");
		savedDataArrList.add("건설");
		savedDataArrList.add("에너지");
	}	
}

 

3) CallDataRepositoryImpl 클래스 정의

package lec14.collectionframework.samplecode08.repository.impl;

import lec14.collectionframework.samplecode08.repository.CallDataRepository;


public class CallDataRepositoryImpl implements CallDataRepository{

	// 싱글톤 패턴 선언
	DataRepository dataRepository = DataRepository.getInstance();
	
	private static CallDataRepositoryImpl instance = new CallDataRepositoryImpl();
	
	public static CallDataRepositoryImpl getInstance() {
		return instance;
	}
	
	// 생성자 : 싱글톤 패턴을 구현하기 위한 프라이빗 접근 제한자를 사용한 기본 생성자
	private CallDataRepositoryImpl(){
		System.out.println("CallDataRepositoryImpl 기본 생성자");
	}
	
	
	@Override
	public Object getNationData(String nationName) {
		return dataRepository.savedDataLkMap.get(nationName);
	}

	@Override
	public String getIndustryData(int paramIndex) {
		return dataRepository.savedDataArrList.get(paramIndex);
	}
	
}

인터페이스를 상속받아 메서드를 정의하는 CallDataRepositoryImpl 를 구현

 

 

5. Service 패키지 구현

1) CallDataService 인터페이스 정의

package lec14.collectionframework.samplecode08.service;

public interface CallDataService {
	
	public Object getNationData(String nationName);
	
	public String getIndustryData(int paramIndex);
	
}

국가데이터 / 산업데이터 가져오는 메서드 뼈대 선언

 

 

2) CallDataServiceImpl 정의

package lec14.collectionframework.samplecode08.service.impl;

import lec14.collectionframework.samplecode08.repository.impl.CallDataRepositoryImpl;
import lec14.collectionframework.samplecode08.service.CallDataService;

// 서비스에서는 업무적인 데이터 처리 작업 구현 (저장, 수정, 삭제 등)
public class CallDataServiceImpl implements CallDataService {

	CallDataRepositoryImpl callDataRepositoryImpl = null;
	
	public CallDataServiceImpl() {
		System.out.println("CallDataServiceImpl 기본 생성자");
		
		// 객체 생성시 싱글톤으로 구현한 CallDataRepositoryImpl 객체 (repository 객체) 를 땡겨옴
		callDataRepositoryImpl = CallDataRepositoryImpl.getInstance();
	}
		
	@Override
	public Object getNationData(String nationName) {
		return callDataRepositoryImpl.getNationData(nationName);
	}

	@Override
	public String getIndustryData(int paramIndex) {
		return callDataRepositoryImpl.getIndustryData(paramIndex);
	}
	
}

서비스 패키지에는 주로 데이터 처리 작업을 구현

생성자에서 객체 생성시 getInstance() 로 싱글톤으로 구현한 CallDataRepositoryImpl 객체를 땡겨옴

 

6. Main 패키지(메소드) 구현

package lec14.collectionframework.samplecode08.main;

import lec14.collectionframework.samplecode08.service.impl.CallDataServiceImpl;

public class MainMethod {
	
	public static CallDataServiceImpl callDataService = new CallDataServiceImpl();
	
	public static void main(String[] args) {
		
		String industryData = callDataService.getIndustryData(1);
		System.out.println("industryData: " + industryData);
		
		Object getNationName = callDataService.getNationData("국가1");
		System.out.println("getNationName : " + getNationName);
	
	}
}

// 출력결과
//CallDataServiceImpl 기본 생성자
//DataRepository 생성자
//CallDataRepositoryImpl 기본 생성자
//industryData: 자동차
//getNationName : 한국

 

7. 기타 코멘트

1) 웹 프로그래밍시, 컨트롤 서비스 리포지토리 세단계 구조로 만듦