❤ 김춘장이의 위키백과 - 나만의 공부 기록 Tistory ❤
시작에 앞서
이번 프로젝트를 하면서 정리하고 있는 나의 포스팅은
거즘 막바지를 다가가고 있다.
그중 코드의 중복성, 가독성 등등 을 고려하여 디자인패턴을 도입하는 것도 하나의 목표였기 때문에
해당 디자인 패턴에 대해서 공부했던 것을 정리하려고 한다
-- 이번 프로젝트 이전 공부 내용 히스토리 --
1번째 포스팅
2023/11/20 👌 JAVA 프로젝트 - 시작과 분석, 그리고 설계
GitHub - gayulz/StudyHistory: 나의 공부 기록 commit 나의 공부 기록 commit . Contribute to gayulz/StudyHistory development by creating an account on GitHub. github.com JAVA 프로젝트 조 구성 : 개인 주제 : 자유주제 기간 : 11월 20
yurizzy.tistory.com
2번째 포스팅
2023/11/21 ~ 2023/11/23☝️ JAVA 프로젝트 - DB설계 & DB 기술 적용
❤ 김춘장이의 위키백과 - 나만의 공부 기록 Tistory ❤ GitHub - gayulz/StudyHistory: 나의 공부 기록 commit 나의 공부 기록 commit . Contribute to gayulz/StudyHistory development by creating an account on GitHub. github.com 이전
yurizzy.tistory.com
3번째 포스팅
2023/11/24 ~ 2023/11/26 ✌️ 프로시저 & 커서의 굴레
❤ 김춘장이의 위키백과 - 나만의 공부 기록 Tistory ❤ GitHub - gayulz/StudyHistory: 나의 공부 기록 commit 나의 공부 기록 commit . Contribute to gayulz/StudyHistory development by creating an account on GitHub. github.com 시작
yurizzy.tistory.com
4번째 포스팅
2023/11/27 ~ 2023/11/29🤘 JAVA GUI Swing
❤ 김춘장이의 위키백과 - 나만의 공부 기록 Tistory ❤ GitHub - gayulz/StudyHistory: 나의 공부 기록 commit 나의 공부 기록 commit . Contribute to gayulz/StudyHistory development by creating an account on GitHub. github.com 사건
yurizzy.tistory.com
디자인 패턴
프로그래밍의 디자인 패턴은 소프트웨어 디자인에서 반복적으로 발생하는 문제에 대한
해결책을 제공하는 재사용 가능한 설계 디자인이다. 이 패턴은 공통된 문제들에 대한 효과적인 해결 방법을 제공하며
개발자들이 이미 검증된 설계 패러다임을 활용하여 소프트웨어를 개발할 수 있도록 도와준다
디자인 패턴에 대한 GoF 디자인패턴 책을 사면서 가장 처음 나오는 말은
“바퀴를 다시 발명하지 마라(Don’t reinvent the wheel)”이다
이미 만들어져서 잘 되는 것을 처음부터 다시 만들 필요가 없다는 의미이다
이 말처럼 디자인 패턴은 설계에 대해 좀 더 쉽게 다가갈 수 있도록 하는 기술이다
그렇기 때문에 개발자라면 공부하는 게 좋다고 생각한다
디자인 패턴은 크게 3가지 패턴으로 분류한다
1. 생성 Creational 패턴
객체의 생성과 초기화에 관련된 패턴
주로 객체를 생성을 추상화하고 시스템이 어떻게 객체를 생성, 조합, 표현하는지에 대한 문제를 다룬다
Singleton , Factory Method, Abstact Factory 등 이 포함된다
2. 구조 Structural 패턴
클래스와 객체를 조합하여 더 큰 구조를 만드는 방법에 관련된 패턴이다
시스템의 구조를 설계하고 클래스나 객체 간의 관계를 정의하는 데 사용한다
Adapter , Decorator , Command 등 포함된다
3. 행위 Behavioral 패턴
객체 간의 알고리즘 및 책임 분재에 관련된 패턴이다
객체 간의 효과적인 의사소통과 책임을 분배하는 방법을 다룬다
Observer, Stategy 등 포함된다
디자인 패턴은 소프트웨어 개발에 문제 해결을 위한 일반적인 지침이라고 보면 된다
코드 재사용성과 확장성 유지보수성을 향상하는데 도움이 된다
이번에 공부한 디자인 패턴은 싱글톤과 상태패턴인데 , 정리해보자 한다
싱글톤 패턴부터 시작해 보자!
SingleTon Pattern
정의
클래스가 하나의 인스턴스를 가지고 이에 대한 전역적인 접근점을 제공하는 패턴이다
이 패턴은 특정 클래스의 인스턴스가 오직 하나만 존재하도록 하고, 이에 대한 전역적인 접근을 제공하며 객체 생성 및 리소스 사용을 효율적으로 관리한다
특징
👉 유일한 인스턴스 : 클래스의 인스턴스가 하나만 생성되며 어디서든지 이에 접근할 수 있다
👉 전역적인 접근점 : 해당 클래스의 인스턴스에 접근할 수 있는 방법을 제공한다
👉 게으른 로딩(지연로딩) : 인스턴스가 필요한 시점에 생성한다
단점
👉 단일 책임 원칙 위배 가능성
주로 전역 상태를 관리하는데 싱글톤 패턴을 사용한다, 단일 책임 원칙을 위해할 가능성이 있는데 테스트하기 어려울 수 있다
👉 강한 결합
다른 클래스들에서 싱글턴을 참조하면 결합도가 높아지는데 이로 인해 유지보수와 테스트가 어려워질 수 있다
👉 멀티스레드 환경에 동기화 문제
멀티스레드 환경에서 동시에 인스턴스를 생성할 가능성이 있다, 동기화를 고려해야 하는데 이때 성능 이슈가 있을 수 있다
👉 의존성 증가
싱글톤에 의존하는 클래스가 많아지면 의존성이 증가하며 변경이 어려워질 수 있다
기본적인 사용 방법
public class SearchFrame {
private SearchFrame(){}
private static SearchFrame INSTANCE=null;
public static SearchFrame getInstance(){
if (INSTANCE == null) INSTANCE = new SearchFrame();
return INSTANCE;
}
}
// 내가 구현한 싱글톤 예제
public class SearchFrame implements mainSettingInf, ActionListener {
// 싱글톤 구간
private SearchFrame(){}
private static class holderInstance{
public static final SearchFrame INSTANCE = new SearchFrame();
}
public static SearchFrame getInstance(){
return holderInstance.INSTANCE;
}
}
내가 구현한 싱글톤 예제는 내부 클래스를 이용하여 게으른 로딩을 사용했다
스레드 안전성이 보장되며 인스턴스 생성을 JVM에게 위임하여 인스턴스를 생성을 보장하면서
실제 인스턴스가 필요한 시점까지 생성을 지연시키도록 한다.
State Pattern
개요
객체의 상태에 따라 객체의 행동을 변경하는 행위 패턴 중 하나입니다.
객체가 특정 상태에 따라 행위를 달리하는 상황에서 “상태를 객체화”하여 상태가 행동을 할 수 있도록 위임하는 패턴입니다
조건문으로 검사하여 행위를 다르게 행동하는 전략패턴과 유사하지만
’ 전략’을 클래스로 표현한 전략 패턴과 달리 상태 패턴은 ‘객체 상태’를 클래스로 표현한 패턴입니다
정의
어떤 행위를 수행할 때 상태에 행위를 수행하도록 위임하고 각 상태를 클래스로 분리해 표현한다
각 클래스에서 수행하는 행위들을 메서드로 구현한다
외부로부터 캡슐화하기 위해 인터페이스를 생성하여 시스템의 각 상태를 나타내는 클래스로 실체화시킨다
주요 구성 요소
👉 Context (콘텍스트)
상태를 가지고 있는 객체, ConcreteState 객체를 참조하고 현재 상태에 따라 다른 행동을 위임한다
👉 State (상태)
추상 클래스 또는 인터페이스로서 Context의 상태에 대한 인터페이스를 정의한다
ConcreteState 클래스들은 이를 구현하기 위해 각각의 상태에 따른 행동을 정의한다
👉 ConcreteState (구체적인 상태)
State를 구현하는 구체적인 클래스로써, 상태에. 따라 특정 행동을 정의한다
장점
👉 유연성과 확장성
상태에 따른 행동을 캡슐화 함으로써 새로운 상태를 추가하거나 기존 상태를 변경하는 것이 비교적 간단하다
👉 가독성 향상
각각의 상태를 별도의 클래스로 정의함으로 가독성이 향상된다, 특정 상태에 대한 로직이 해당 상태 클래스 내부에
캡슐화되어있어 코드 이해가 용이하다
👉 상태 전이 관리 용이
객체의 상태 전이를 명시적으로 정의하고 캡슐화 함으로 전이 관리가 용이하며 버그를 줄일 수 있다
👉 클라이언트 코드 단순화
클라이언트 코드에서 현재 객체의 상태를 직접 확인하고 조건에 따라 다른 동작을 구현할 필요가 없다
대신에 현재 상태에 따라 자동으로 올바른 동작이 수행되므로 클라이언트 코드가 단순화된다
단점
👉 클래스 개수 증가
상태 패턴을 사용하면 각 상태를 별도의 클래스로 정의해야 하므로 클래스의 수가 증가할 수 있다
이는 작은 규모의 프로젝트는 괜찮지만 대규모 프로젝트에서는 클래스 증가로 관리가 어려울 수 있다
👉 상태 변화에 대한 비용
객체의 상태가 변경될 때마다 새로운 객체를 생성해야 하는 경우가 있다, 메모리 사용량을 높일 수 있고 객체 생성 및 소멸에 따른 비용이
발생될 수 있다
👉 복잡성 증가
각 상태를 별도의 클래스로 분리함으로써 상태 간의 공통된 로직이 중복될 수 있다.
👉 상태 전이의 명시적 표현 필요
상태 패턴을 사용 시 상태 전이가 명시적으로 정의돼야 하는데 모든 가능한 상태 전이를 명확하게 파악하고 정의해야 하므로 관리가 중요하다
이번에 작성한 소스코드입니다
package controller;
import changeFrame.*;
import javax.swing.*;
public class Context {
private mainSettingInf currentState;
private JFrame frame;
public Context(mainSettingInf ini, JFrame frame){
this.currentState = ini;
this.frame = frame;
}
public void setSate(mainSettingInf state){
this.currentState = state;
}
public void request(){
frame.getContentPane().removeAll();
currentState.transferActions(frame, this);
}
}
package changeFrame;
import actions.ActionHandler;
import actions.CheckRoutine;
import controller.Context;
import javax.swing.*;
import java.awt.*;
public interface mainSettingInf {
Tools tool = Tools.getInstance();
Images iBtn = Images.getInstance();
void transferActions(JFrame frame, Context context);
ActionHandler handler = new ActionHandler();
Images img = Images.getInstance();
CheckRoutine check = CheckRoutine.getInstance();
// 배경화면 가져오기
static JPanel getMainImg(){
Image backgroundImage = new ImageIcon("src/image/subBackground.jpg").getImage();
JPanel background = new JPanel(){
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(backgroundImage, 0, 0, this);
}
};
background.setLayout(null);
return background;
}
}
package changeFrame;
import controller.Context;
import dto.CustomerDTO;
import dto.RoomInfo;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class BookingFrame implements mainSettingInf, ActionListener {
// 싱글톤 구간
private BookingFrame(){}
private static class holderInstance{
public static final BookingFrame INSTANCE = new BookingFrame(); }
public static BookingFrame getInstance() {return holderInstance.INSTANCE;}
// 멤버변수 선언부
private JFrame frames;
private Context contexts;
private final JPanel background = mainSettingInf.getMainImg();
private static JComboBox payCombo;
private static JTextField nameIn, phoneIn;
private static JPasswordField passIn;
private JPanel eastPan;
private JPanel westPan;
private JLabel customerInfo, name, phone, pass, payment, selectRoomInfo;
private JTextArea bookingRoomInfo;
private JButton backBtn;
private JButton summitBtn;
private CustomerDTO customer;
// 오버라이드
@Override
public void transferActions(JFrame frame, Context context) {
frame.getContentPane().add(background, BorderLayout.CENTER);
this.frames = frame;
this.contexts = context;
westPanelSetting();
EastPanelSetting();
addButtons();
addListeners();
frame.revalidate();
frame.repaint();
}
// 리스너 클래스로 전달
@Override
public void actionPerformed(ActionEvent e) {
customer = CustomerDTO.getInstance();
customer.setCustomerName(nameIn.getText());
customer.setCustomerPhone(phoneIn.getText());
customer.setPassword(passIn.getText());
customer.setPaymentInfo(payCombo.getSelectedItem().toString());
if (e.getSource() instanceof JButton) handler.handleButtonEvent((JButton) e.getSource(), frames, contexts);
}
// 버튼 등록 메서드
private void addButtons() {
summitBtn = iBtn.rightImgButton("booking");
backBtn = iBtn.leftImgButton("back");
background.add(summitBtn);
background.add(backBtn);
}
// 리스너 등록
private void addListeners() {
nameIn.addActionListener(this);
phoneIn.addActionListener(this);
passIn.addActionListener(this);
payCombo.addActionListener(this);
backBtn.addActionListener(this);
summitBtn.addActionListener(this);
}
// East Penel 등록
private void EastPanelSetting() {
eastPan = new JPanel();
selectRoomInfo = tool.titleLabel("선택 숙소정보");
background.add(eastPan);
background.add(selectRoomInfo);
selectRoomInfo.setBounds(370, 280, 200, 100);
eastPan.setBounds(350, 400, 400, 470);
bookingRoomInfo = new JTextArea(30, 25);
bookingRoomInfo.setFont(tool.getPlainfont(16));
bookingRoomInfo.setLineWrap(true); // 자동 줄바꿈 설정
bookingRoomInfo.setEditable(false); // 읽기모드
JTextAreaPrint();
eastPan.add(bookingRoomInfo, "Center");
eastPan.setBackground(new Color(255, 0, 0, 0));
}
// 숙소 정보 출력 기능 메서드
private void JTextAreaPrint() {
Funtions fn = Funtions.getInstance();
List<RoomInfo> userNeedsRooms = RoomViewFrame.getUserNeedsRooms();
String roomInfoText = String.valueOf(fn.printLodgingInfo(userNeedsRooms));
bookingRoomInfo.setText(roomInfoText);
}
// west Panel 등록
private void westPanelSetting() {
westPan = new JPanel();
westPan.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 20));
customerInfo = tool.titleLabel("예약 정보 등록");
name = tool.settingLabel("예약자 성함");
phone = tool.settingLabel("예약자 연락처");
pass = tool.settingLabel("예약 비밀번호");
payment = tool.settingLabel("결제 선택");
payCombo = tool.settingCombo();
payCombo.setOpaque(true);
nameIn = tool.settingFiled(13);
phoneIn = tool.settingFiled(13);
passIn = tool.setPasswordField(13);
westPan.add(name);
westPan.add(nameIn);
westPan.add(phone);
westPan.add(phoneIn);
westPan.add(pass);
westPan.add(passIn);
westPan.add(payment);
westPan.add(payCombo);
background.add(customerInfo);
background.add(westPan);
customerInfo.setBounds(75, 280, 150, 100);
westPan.setBounds(75, 400, 250, 470);
westPan.setBackground(new Color(255, 0, 0, 0));
}
// getter
public JButton getBackBtn() {return backBtn;}
public JButton getSummitBtn() {return summitBtn;}
public CustomerDTO getCustomer() { return customer; }
}
오버라이드 한 추상메서드입니다
추상메서드를 구체화시켰는데 이걸 가지고 프레임을 교체하는 로직으로 처리했습니다
이렇게 하면 카드레이아웃을 쓰지 않더라도 상태 패탄으로도 구현이 가능합니다
이번 포스팅은 두 가지 패턴에 대해서 알아봤는데요
프로젝트는 끝났지만 오류를 해결하기 위해 아직도 수정 중입니다
중간중간 추가 업데이트 하도록 하겠습니다
'👩🏻💻 𝐋𝐚𝐧𝐠𝐮𝐚𝐠𝐞 > ⠀⠀⠀⠀ Jᴀᴠᴀ' 카테고리의 다른 글
Java의 상수, 매직넘버란 ? (0) | 2024.04.28 |
---|---|
일급 컬렉션 (First Class Collection) (0) | 2024.04.28 |
2023/11/27 ~ 2023/11/29🤘 JAVA GUI Swing (0) | 2023.12.04 |
2023/11/20 👌 JAVA 프로젝트 - 시작과 분석, 그리고 설계 (0) | 2023.12.03 |
2023/11/17 💛 상속과 인터페이스 미니과제 (1) | 2023.11.20 |