67일: GoF, Lambda(Consumer,Predicate,Supplier,RuntimeException), 자바에서 표준메소드 작성, 익명 객체를 이용한 스레드, Controller

Jiwontwopunch·2022년 2월 18일
0

국비기록

목록 보기
67/121
post-thumbnail

2022.02.18.Fri.

✍ 복습

GoF(Gang of Four) 디자인 패턴

출처 : https://velog.io/@namezin/GoF-design-pattern

Factory

  • 객체를 생성하는 데 복잡한 옵션이나 정보가 필요. 대신 설정해 주는 클래스
  • MyBatis의 경우 DataSource를 입력받아 SqlSession을 생성한 다음 SqlSession을 이용해 CRUD 처리
  • active시 최대 연결은 몇개? idle시(프로세스가 실행하고 있지 않은 상태) 최대 연결 몇개? 타임아웃시간?.....설정을 잡을 수 있는데 설정을 안잡으면 SqlSession을 안만들건가? 적절하게 초기화해서 객체를 만들어주는 공장
  • 마이바티스의 SqlSessionFactory는 DataSource를 입력받아 SqlSession을 편리하게 사용할 수 있는 SqlSessionTemplate을 만들어준다.

Builder

  • 객체 생성의 난해함(예를들어 필드가 String 10개)을 덜어준다.

Facade

  • 표준 인터페이스 + 인터페이스를 구현한 구상(concrete) 클래스
  • 표준을 가지고 작업을 하면 구상 클래스를 필요에 따라 교체하면서 사용

자바에서 표준메소드 작성하기

  • 스레드 : 메소드가 병렬 실행
  • 스레드가 실행될 때 윈도우로부터 일정 실행시간을 지정받는다(time slice). 시간이 지나면 실행을 양보한다
  • 만약 2초 걸리는 A스레드, 3초 걸리는 B 스레드가 있다면. 그리고 타임 슬라이스가 0.1초라면
  A		  B		   A			B
 0.1     0.1   0.1(0.2)	    0.1(0.2).....
  • 자바는 스레드 클래스를 제공하기 때문에 간단하게 병렬 작업을 할 수 있다
  • 단 자바가 병렬로 돌릴 작업이 뭔지는 모른다 → 프로그래머가 작성해야 한다 → 이름이 run으로 정해져 있다
  • 자바에서 표준메소드를 작성하려면 인터페이스를 implements해야 한다
class MyRunnable implements Runnable {
	@Override
	public void run() {
		for(int i=1; i<=10; i++)
			System.out.println("### MyRunnable 실행 중 : " + (i*10) + "% 완료 ###");
	}
}

public class Test2 {
	public static void main(String[] args) {
		MyRunnable myRunnable = new MyRunnable();
		
		// new Thread하는데 왜 객체를 넘긴다? 실제로는 메소드를 넘긴 것
		// 	js에서는 함수만 넘길 수 있다. new Thread(function() { });
		new Thread(myRunnable).start();
		System.out.println("메인 스레드 종료");
	}
}

익명 객체를 이용한 스레드

  • boilerplate : 작업 할 때 반복되는 코드
  • 자바에서 js처럼 함수를 파라미터로 넘기고 싶다. 근데 자바는 인터페이스를 구현한 객체를 생성해야 한다 → boilerplate를 제거하자
public class Test3 {
	public static void main(String[] args) {
		// Runnable은 만들어야 하는데...클래스까지 만들 필요는 없잖아...파라미터로 Runnable을 넘기자
		
		// Thread 생성자의 파라미터가 Runnable이라는 사실을 자바가 알고 있다
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("익명 객체를 이용한 스레드");
			}
		}).start();
		
		// 그렇다면 프로그래머는 run()의 내부만 만들자 -> 객체는 자바가 만들면 되잖아 : 자바 Lambda
		// 메소드만 만들면 자바가 객체를 알아서 생성해준다 -> 전제조건 : 인터페이스가 존재해야만 한다
		new Thread(
			()->{System.out.println("익명 객체를 이용한 스레드");}
		);
	}
}

람다식 예시

// 람다식을 이용해 간편하게 함수를 작성하려면...많은 작업이 필요하다

// 람다식을 사용하려면 추상 메소드를 하나가진 인터페이스가 바람직
@FunctionalInterface
interface 인사 {
	public void hello();
}

class 학생 {
	public void 꾸벅(인사 insa) {
		insa.hello();
	}
}

public class Test4 {
	public static void main(String[] args) {
		// 인터페이스가 있고 그 인터페이스를 이용하는 클래스가 있어야만 람다식을 사용할 수 있다
		// 람다를 사용하려니 배보다 배꼽이 크다 -> 자바는 java.util.function 패키지를 이용해 FunctionInterface를 제공
		학생 s = new 학생();
		s.꾸벅(()->{ System.out.println("안녕하세요"); });
	}
}

Consumer

입력은 있고 리턴은 없다

class ConsumerSample implements Consumer<Integer> {
	@Override
	public void accept(Integer t) {
		System.out.println(t);
	}
}

public class Test5 {
	public static void main(String[] args) {
		// Arrays.asList는 배열을 리스트로 변환하는 함수. 읽기전용이다
		List<Integer> list = Arrays.asList(11,22,33,44,55);
		
		// ConsumerSample을 사용한 예 : ?의 구체적 의미가 궁금해서 iilii.eloos.com에서 generic 강좌를 보세요
		list.forEach(new ConsumerSample());

		
		
		// 람다식을 사용한 예
		// list.forEach((xx)->{ System.out.println(xx); });
		
		// 처리하는 코드가 한 줄이면 {}를 생략할 수 있다. {}를 생략하면 ;이 오면 안된다 
		//list.forEach((xx)->System.out.println(xx));
		
		// 파라미터가 하나면 ()를 생략할 수 있다(하나일때만 생략 가능)
		//list.forEach(a->System.out.println(a));
		
		// 파라미터에 대해 어떤 처리도 하지 않는다면....윗줄의 경우 xx가 들어와서 그대로 xx를 출력한다...생략하자
		// 이렇게 파라미터를 생략하고 함수를 사용하는 것을 "메소드 참조"라고 한다
		list.forEach(System.out::println);
		
	}
}

Predicate

입력이 있고 출력은 boolean → 조건 체크

class SamplePredicator implements Predicate<Integer> {
	@Override
	public boolean test(Integer t) {
		return t%2==0;
	}
}

public class Test6 {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(11,22,33,44,55);
		
		// 람다식을 이용해 작업하도록 만들어진 자바 기술이 Java Stream API
		// 리스트를 스트림을 변환하면 자바가 제공하는 함수를 이용해 람다식을 연속으로 사용할 수 있다
		// filter는 list를 모든 원소를 차례로 입력받아 조건을 만족하는 것만 걸러낸다
		// 스트림에는 메소드에는 중간에서 필터링 또는 변경하는 중간 메소드가 있고 최종 소비를 하는 메소드가 있다
		list.stream().filter(a->a%2==0).forEach(System.out::println);
		
		// list로 부터 조건을 만족하는 원소만 뽑아서 리스트를 작성하고 싶다면
		List<Integer> result = list.stream().filter(a->a%2==0).collect(Collectors.toList());
		
		System.out.println(list.stream().filter(a->a%2==0).count());
	}
}

Supplier

입력은 없고 출력은 있다

import java.util.*;
import java.util.function.*;

class SupplierSample1 implements Supplier<Integer> {
	@Override
	public Integer get() {
		// 입력은 없고 출력은 있다
		return 1;
	}
}

// 우리가 사용할 서플라이어 형식 : 
class SupplierSample2 implements Supplier<RuntimeException> {
	@Override
	public RuntimeException get() {
		return new RuntimeException();
	}
}

public class Test7 {
	public static void main(String[] args) {
		// java.util.Optional : NullPointerException에 대한 자바의 대응
		//	리턴값이 반드시 존재할 경우  :  public User searchUser(String username) { }
		// 리턴값이 존재하지 않을 수 있는 경우 : public Optional<User> searchUser(String username) { }
		
		// dao에서 Optional로 result가 리턴되어 왔다고 하자
		Optional<Integer> result = Optional.ofNullable(null);
		
		// result에 들어있을 수 있는 Integer를 꺼내려면 get() -> 단 값이 없으면 NoSuchElementException 예외 발생
		// Integer value1 = result.get();
		
		// 예외를 내가 원하는 예외로 바꿔주자
		// 스프링에는 예외를 전담하는 컨트롤러가 있다(@ControllerAdvice)
		// 검색 실패와 같이 내가 원하지 않는 결과가 나왔을 때 적절한 예외를 발생시켜 ControllerAdvice를 부르자
		// 즉 작업을 할 때 바람직한 상황은 Controller에 작성, 원하지않는 상황은 ControllerAdvice에 작성하자
		result.orElseThrow(()->new RuntimeException());
		
		result.orElseThrow(RuntimeException::new);
		
	}
}

RuntimeException (예외 처리)

  • try ~ catch 사용하지 않으려고 RuntimeException 사용
  • 체크하는 예외 : try~catch 필요
  • 체크하지 않는 예외 : 가벼운 예외로 RuntimeException의 자식. 예외처리 코드는 작성하지 않아도 상관없다
public class BoardNotFoundException extends RuntimeException {

}

Lambda Test 1

Lambda Test 2

Controller

MVC(Model View Controller) : Model:데이터, View: 화면

백엔드에서 View를 포함하고 있다 → 백엔드와 뷰가 함께 작업한다. 즉 자바 객체를 보내줘도 타임리프나 jsp는 처리할 수 있다

	@GetMapping("/test1")
	public ModelAndView test1(Integer pno) {
		return new ModelAndView("test1").addObject(new Product(pno, pno+"번 상품"));
	}

REST

데이터만 있다 → 그러면 데이터를 어떻게 클라이언트쪽으로 출력할까? (자바 객체는 안된다), 스프링 부트의 경우 JSON으로 내보낸다.

  • 입력 형식을 지정 : PropertyEditor
  • 출력 형식을 지정 : MessageConverter
  • 스프링 부트 프로젝트를 만들면 JSON을 처리하는 Jackson 라이브러리가 자동포함되고 JSON에 대한 메시지 컨버터로 잭슨 자신을 등록한다
  • Jackson, Gson 등 JSON 라이브러리가 포함되지 않은 경우 메시지 컨버팅에 실패(415. unsupported media type)
	@GetMapping(value="/test2", produces = MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody Product test2(Integer pno) {
		return new Product(pno, pno+"번 상품");
	}
	
	// @RequestBody, @ResponseBody
	// request, response를 편지에 비유하자면 편지봉투가 있고 편지지가 있다
	// (보내는 주소, 요청 주소, 데이터의 길이) 등 편지봉투에 해당하는 것이 헤더, 내용에 해당하는 것이 바디
	// urlencoded로 요청, 응답 바디에 여러개의 값을 담아서 보낼 수 있다 
	// json의 경우는 단일 json이 요청 객체, 또는 응답 객체의 바디를 가득 채운다
	//    @RequestBody는 요청 객체의 바디 전체를 꺼내서 JSON으로 바꿔라
	
	@GetMapping("/example01")
	public void test2View() {
	}

SampleController 아래 entity를 공통으로 사용

0개의 댓글