Factory Pattern 팩토리 패턴은 객체 생성을 추상화하여 한 군데서 관리하는 패턴으로 상속 관계에 있는 두 객체에서 상위 객체가 추상화된 생성화 부분을, 하위 객체과 구체적인 구현을 담당한다. 상위 객체는 세부 구현 내용을 몰라도 되고 하위 객체에서 코드 수정이 생기면 그 부분만 수정하면 되기 때문에 두 객체의 의존성이 줄어든다. 이번 시간에는 이 Factory Pattern을 활용하여 객체 생성하는 부분을 함수형으로 프로그래밍해볼 것이다. 우선 지난 시간에 구현한 Car을 Abstract Class로 변경하고 각각 SUV, Sedan, Ven 객체를 구현한다. 이제 이 Car를 만드는 CarFactory를 만들어본다. 팩토리 클래스는 주로 Static method를 사용하며 차
Method Reference 자바는 오랜 기간 OOP 프로그래밍으로 개발되어 왔다. 따라서 기존 라이브러리들도 모두 Class(Object) 기반이다. FP 방식으로 프로그래밍하면 기존의 Class 기반의 메소드를 사용할 수 없을까?? Java에서는 Method Reference를 사용해서 기본 메소드를 함수로 사용할 수 있도록 했다. Method Reference는 크게 4 가지 방법이 있다. 1) 클래스의 static method를 사용할 때, 2) 선언된 객체의 instance method를 사용할 때, 3) 객체의 instance method를 사용할 때, 4) 클래스의 constructor를 사용할 때, 상황에 맞게 위 케이스에서 골라서 사용하면 된다. 클래스의 static method를 사용할 때 static method는 객체를 생성하지 않고 클래스명.메소드명으로 호출 가능한 메소드를 뜻한다. 인스턴스를 생성하지 않고 사용 가능하
Comparator Comparator는 두 개의 파라미터를 받는 함수다. 내부에는 compare라는 추상 함수를 가지고 있으며 이 추상 함수는 건네받은 값들을 비교해서 더 작으면 음수, 같으면 0, 크면 양수를 출력하도록 구현해야한다. Comparator 함수는 단독으로 잘 쓰이지 않으며 Collection 내부의 sort와 함께 쓰인다. Collection 내부 sort 형태는 아래와 같다. List 내부의 Sort와 매핑해주는 것이 전부지만 결국 Java 내부에서 정렬할 때, Comparator를 쓰는 것을 알 수 있다. Java 얕은 복사 vs 깊은 복사 자바에서 메모리는 스택 메모리와 힙 메모리로 구분된다. 스택 메모리에서는 원시값, 또는 식별자(변수명) 등을 저장하며 구현된 객체(클래스 등)는 힙 메모리에 저장된다. 이때 메모리 낭비를 막기 위해서 객체를 복사할 때, "두 개의 식별자가 하나의 객체를 가르키도록" 하는 얕은 복사를 쓴다.
Predicate Predicate는 해당 값이 참인지 거짓인지 구분해주는 함수다. test라는 추상 메소드를 가지고 있으며 하나의 파라미터를 받을 수 있다. 예를 들어 Integer를 받아와서 해당 값이 0보다 큰 지 구분하는 기능은 아래와 같다. Predicate & forEach = Filter 이전에 구현했던 ForEach와 Predicate를 조합하면 Filter를 구현할 수 있다. Filter는 List를 받아와서 넘겨 받은 Predicate가 참인 값만 추린 List를 반환하는 함수다. 예를 들어 1~5까지 수가 담겨있는 리스트에서 3 이상의 값만 추려내는 fillter를 구현하면 아래와 같다. 추가적으로 forEach와 적절히 조합하여 하나씩 출력할 수 있다.
Consumer Consumer는 accept라는 추상 메소드를 가지고 있다. accept는 별도의 return 값을 가지고 있지 않다. 즉 함수 내부에서 모든 동작을 마무리 한다. 예를 들면 다음과 같다. 제네릭 타입과 연계 - ForEach 만들기 Consumer와 제네릭 타입을 조합하면 ForEach를 구현할 수 있다. ForEach는 이터러블한 객체를 돌면서 각 요소마다 넘겨받은 함수를 실행시켜주는 함수다. 예를 들어 Integer List와 Double List를 넘겨주고 각각 출력해주는 ForEach 함수를 구현하면 아래와 같다. BiConsumer BiConsumer는 파라미터 값이 두개인 Consumer다. 이 BiConsumer를 사용하면 index 값을 추가로 넘겨줄 수 있는 ForEach를 만들 수 있다. 오버로딩을 사용해서 BiConsumer를 파라미터로 받는 ForEach를 구현할 수 있다.  추상메소드를 통해 return 값을 받아올 수 있다. 단순히 보면 그냥 "hello world"를 반환하는 함수를 만들거나 변수에 바로 넣으면 되는데 왜 귀찮게 Supplier를 사용하는 것일까?? 실행 시기 결정 가능 - Lazy Evaluation 3초 후, random 값을 반환하는 함수를 구현했다고 하자, 입력된 카운트 수 만큼 random 값을 출력하되 짝수 count 일 때만 출력한다면 총 얼만큼의 시간이 걸릴까? 카운트를 5만큼 주면 0, 2, 4 일때만 출력되기 때문에 약 9 + @ 만큼의 시간이 걸릴 것이라고 추측할 수 있다. 그러나 실제 코드를 돌려보면 다르다.  객체지향 프로그래밍은 명령형 프로그래밍으로 추상화한 객체에게 행동을 위임하는 방식의 프로그래밍 기법입니다.
들어가며 최근 인프런 기술 과제 및 면접을 준비하면서(후기 남길 예정) SQL의 중요성과 함수형 프로그래밍의 기초를 몸소 느꼈다. 인프런이라면 내가 준비하던 기술 스택을 전환할 의지가 만땅이였지만 아쉽게도 1차 면접 탈락했기 때문에 Typescript로의 전환은 하지 않을 것이다. 그렇다면 Java에서 이 함수형 프로그래밍을 사용하고 싶어서 검색해보니 Java 8 부터 함수형 프로그래밍을 지원해주고 더 나아가 코틀린을 통해서 더욱 쉽게 사용할 수 있다고 한다. 따라서 이번 사이드 프로젝트에서는 대표적인 OOP 언어인 자바에서는 어떻게 함수형 프로그래밍을 다루는 지에 대해 공부해보려고 한다. 프로젝트 환경
Account 구현 클래스 다이어그램 소스코드 Account CalculateIntrestBehavior WithdrawBehavior CalculateIntrestWithMinus CalculateIntrestWithNomal CalculateIntrestWithSaving WithdrawWithMinus WithdrawWithNomal WithdrawWithSaving Minus Nomal Saving AccountSimulator 실행 결과 ![](https://images.velog.io/images/carrykim/post/c392e058-15f6-4a9e-80ff-475