김기헌
IoC (Inversion of Control, 제어의 역전)
•
Factory 적용
package com.line.dao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserDaoFactory {
@Bean
public UserDao awsUserDao(){
AwsConnectionMaker awsConnectionMaker = new AwsConnectionMaker();
UserDao userDao = new UserDao(awsConnectionMaker);
return userDao;
}
@Bean
public UserDao localUserDao(){
UserDao userDao = new UserDao(new LocalConnectionMaker());
return userDao;
//return new(UserDao(new LocalConnectionMaker));
}
}
Java
복사
싱글톤 패턴(Singleton pattern)
•
싱글톤 패턴이란?
객체의 인스턴스가 오직 1개만 생성되는 패턴
•
싱글톤 패턴의 장점
◦
메모리
최초 한번의 new 연산자를 통해서 고정된 메모리 영역을 사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있다. 뿐만 아니라 이미 생성된 인스턴스를 활용하니 속도 측면에서도 이점이 있다고 볼 수 있다.
◦
다른 클래스 간에 데이터 공유의 용이함
싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있다. 하지만 여러 클래스의 인스턴스에서 싱글톤 인스턴스의 데이터에 동시에 접근하게 되면 동시성 문제가 발생할 수 있으니 이점을 유의해서 설계하는 것이 좋다.
이 외에도 도메인 관점에서 인스턴스가 한 개만 존재하는 것을 보증하고 싶은 경우 싱글톤 패턴을 사용하기도 한다.
싱글톤 패턴을 적용하면 위와 같은 효율에서의 이점을 얻을 수 있다. 하지만 싱글톤 패턴이 다음과 같은 많은 문제점들을 수반하기 때문에 trade-off를 잘 고려해야 한다.
•
싱글톤 패턴의 문제점
◦
싱글톤 패턴을 구현하는 코드 자체가 많이 필요하다
앞서 소개한 구현 방법외에도 정적 팩토리 메서드에서 객체 생성을 확인하고 생성자를 호출하는 경우에 멀티스레딩 환경에서 발생할 수 있는 동시성 문제 해결을 위해 syncronized 키워드를 사용해야 한다.
◦
테스트의 어려움
싱글톤 인스턴스는 자원을 공유하고 있기 때문에 테스트가 결정적으로 격리된 환경에서 수행되려면 매번 인스턴스의 상태를 초기화시켜주어야 한다. 그렇지 않으면 어플리케이션 전역에서 상태를 공유하기 때문에 테스트가 온전하게 수행되지 못한다.
◦
의존 관계상 클라이언트가 구체 클래스에 의존하게 된다
new 키워드를 직접 사용하여 클래스 안에서 객체를 생성하고 있으므로, 이는 SOLID 원칙 중 DIP를 위반하게 되고 OCP 원칙 또한 위반할 가능성이 높다.
◦
이외에도 자식클래스를 만들수 없다는 점과, 내부 상태를 변경하기 어렵다는 점 등 여러가지 문제들이 존재한다. 결과적으로 이러한 문제들을 안고있는 싱글톤 패턴은 유연성이 많이 떨어지는 패턴이라고 할 수 있다.
김상호
스택이란?
스택은 데이터를 일시적으로 저장하기 위해 사용하는 ‘자료구조’이다.
데이터의 입출력 순서는 LIFO(Last In First Out) 이다.
스택의 구조
•
가장 먼저 저장되는 데이터는 스택의 아래 쪽(높은 주소)부터 쌓이고, 다음 저장되는 데이터가 바로 그 위(낮은 주소)에 쌓입니다.
그림과 같이 스택 안에 새로운 데이터를 추가할땐 Push를 사용합니다.
데이터는 스택의 아래쪽부터 쌓이게 됩니다.
다음은 데이터를 다시 빼내는 Pop입니다.
이처럼 스택은 Push/Pop으로 데이터를 추가와 제거를 하게 됩니다.
추가로 .peek() ⇒ 맨 위의 값을 확인하는 기능
.isEmpty() ⇒ 스택이 비었는지 체크하는 기능
이가현
알고리즘
stack구현(Last In First out)
•
함수에서 함수 호출하는 기능을 구현하기 위해
•
4가지 기능
◦
push() → 맨위에 추가
◦
pop() → 맨위에부터 꺼내기
◦
peek() → 맨위에꺼 출력
◦
isEmpty() → 비었는지 check하는 기능
.push()구현
→ stack은 array 확장 기능
public class Stack01 {
private int[] arr = new int[10000];
private int lastestIndex=0;
public Stack01() {
}
public Stack01(int size) {
this.arr = new int[size];
}
public int pop(){
int value = this.arr[this.lastestIndex-1];
this.lastestIndex--;
return value;
}
public void push(int value) {
this.arr[this.lastestIndex] = value;
this.lastestIndex++;
}
public int[] getArr(){
return arr;
}
}
Java
복사
Test
테스트 만들 때 원칙
1.
negative Test부터 - 안될것 같은 것부터 테스트를 만든다
2.
되는 것 부터 만들지 않고 안되는 것 부터 테스트를 만든다.
3.
언제 실행해도 동일한 결과가 나오게끔 테스트를 구성 해야 합니다.
Factory적용
제어의 역전(Inversion of Control)
•
UserDao가 ConnectionMaker(인터페이스)의 구현체를 결정하는 방식에서 Factory가 사용할 오브젝트를 공급해주는 방식으로 변경
•
UserDao는 실행 기능(수동적)만 하고 Factory는 구현체를 생성하는 책임까지 위임받음.
•
Factory를 도입하는 과정이 바로 제어의 역전을 적용하는 작업
Factory 클래스
public class Factory {
public UserDao localUserDao(){
return new UserDao(connectionMarker());
}
// 사용하는 인터페이스를 명확하게 하기 위해서 분리
public ConnectionMarker connectionMarker(){
return new LocalConnectionMarker();
}
public UserDao awsUserDao(){
return new UserDao(connectionMarker2());
}
// 사용하는 인터페이스를 명확하게 하기 위해서 분리
public ConnectionMarker connectionMarker2(){
return new AWSConnectionMarker();
}
}
Java
복사
UserDao에 Factory 클래스 적용
public class UserDao {
private ConnectionMarker connectionMarker;
// 원래 ConnectionMarker connectionMarker = new LocalConnectionMarker();
public UserDao(ConnectionMarker connectionMarker) {
this.connectionMarker = connectionMarker;
}
// public UserDao(LocalConnectionMarker localConnectionMarker) {
// this.connectionMarker = new LocalConnectionMarker();
// }
public void insert(User user) throws SQLException {
Connection c = connectionMarker.makeConnection();
PreparedStatement pstmt = c.prepareStatement
("INSERT INTO user(id,name,password) VALUES (?,?,?)");
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getName());
pstmt.setString(3, user.getPassword());
pstmt.executeUpdate();
pstmt.close();
c.close();
}
Java
복사
Factory Test
class UserDaoTest {
@Test
void insertAndSelect() throws SQLException {
UserDao userDao = new Factory().awsUserDao();
//factory클래스의 awsUserDao 메서드 사용해서 db연동
String id = "11";
userDao.insert(new User(id, "qwer", "uiop7890"));
// User user = new User(id, "qwer", "uiop7890");
User user = userDao.select(id);
assertEquals("qwer", user.getName());
}
}
Java
복사
Spring 적용
Factory클래스
@Configuration 에서 시작 합니다. → Spring
@RestController / @Controller에서 시작 합니다. → Spring Boot
@Configurable
public class UserDaoFatory {
@Bean
public UserDao localUserDao() {
return new UserDao(new LocalConnectionMaker());
}
}
Java
복사
Test Code Refactoring
테스트 코드에서 Spring ApplicationContext를 사용
임학준
Factory
•
factory는 관계정의의 설계도이다
•
Test가 맡고있는 오브젝트 생성을 factory로 분리한다
public class UserDaoFactory {
public UserDao awsUserDao() {
UserDao userDao = new UserDao(new AwsConnectionMaker());
return userDao;
}
public UserDao localUserDao() {
UserDao userDao = new UserDao(new LocalConnectionMaker());
return userDao;
}
}
Java
복사
•
test 코드의 변화(팩토리 도입전)
@Test
void addandget() throws SQLException {
UserDao userDao = new User(new AwsConnectionMaker());
userDao.deleteAll();
userDao.add(new User("1","hakjun","1234");
}
Java
복사
•
test 코드의 변화(팩토리 도입후)
@Test
void addandget() throws SQLException {
UserDao userDao = new UserDaoFactory().awsUserDao();//변화한 부분
userDao.deleteAll();
userDao.add(new User("1","hakjun","1234");
}
Java
복사
스프링의 적용
•
@Bean = 오브젝트의 생성담당
•
@Configuration = Applicationcontext가 관리하는 오브젝트 요청
•
@Autowired = 필요한 의존 객체의 “타입"에 해당하는 빈을 찾아 주입한다.
//Spring 적용
@Configuration
public class UserDaoFactory {
@Bean
public UserDao awsUserDao() {
UserDao userDao = new UserDao(new AwsConnectionMaker());
return userDao;
}
@Bean
public UserDao localUserDao() {
UserDao userDao = new UserDao(new LocalConnectionMaker());
return userDao;
}
}
Java
복사
//@Bean을 @Test에서 사용할시 Factory의 메소드명을 정확히 입력해야 한다
context.getBean("localUserDao",UserDao.class);
Java
복사
•
@ExtendWith = Junit에서 Sptring ApplicationContext를 쓸 수 있게 해준다
•
@ContetConfituration = @Test코드 실행시 ApplicationContext에 들어갈 관계설정정보를 불러오게 해준다(UserDaoFactory)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = UserDaoFactory.class)
class UserDaoTest{
Java
복사
조국현
최아영
알고리즘 실습
스택 구현
push(), pop() 테스트
Factory 적용
팩토리 메서드 패턴
(Factory method pattern)은 객체지향 디자인 패턴이다. Factory method는 부모(상위) 클래스에 알려지지 않은 구체 클래스를 생성하는 패턴이며. 자식(하위) 클래스가 어떤 객체를 생성할지를 결정하도록 하는 패턴이기도 하다. 부모(상위) 클래스 코드에 구체 클래스 이름을 감추기 위한 방법으로도 사용한다.
Factory Method
Spring 적용
Spring과 Spring Boot의 차이
@Configuration에서 시작 → Spring
@RestController or @Controller에서 시작 → Spring Boot
gradle dependencies에 Spring 추가
Refactoring