1. 디자인 패턴의 정의 및 필요성
방법론이 만들어지는 과정
2. 프로세스 지향 방법
절차적 방법 - 1980년대 대표적인 방법론, 처리순서를 구조화
개요
- 정의: 기능(프로세스)이 중심이 되어 시스템을 설계하는 방법.
- 구성 요소: 기능(프로세스), 데이터.
- 모델 기법: DFD(Data Flow Diagram).
특징
- 프로세스와 데이터의 분리: 기능 중심의 설계로, 프로세스와 데이터가 각각 별개의 것으로 다루어짐.
- 함수 중심의 모듈 구성: 처리 중심의 함수가 우선 결정되며, 데이터는 별도로 존재.
- 실세계 표현의 왜곡: 실세계를 컴퓨터가 처리하는 방식으로 변환하여 표현.
장단점
- 장점: 명확한 처리 순서와 단계 제공.
- 단점: 데이터와 기능의 분리로 인해 복잡성이 증가하고, 유지보수가 어려움.
3. 데이터 지향 방법
개요
- 정의: 데이터가 중심이 되어 시스템을 설계하는 방법.
- 구성 요소: 데이터, 데이터 구조화.
- 대표적 소프트웨어 개발 방법론: 정보공학 방법론, E-R 다이어그램.
- 데이터 중심: 시스템이 취급하는 데이터를 먼저 구조화하고, 이를 기반으로 기능을 설계.
- 기업 비즈니스 시스템 적용: 기업의 업무 프로세스는 수시로 변하지만 데이터는 대부분 그대로이므로 데이터 중심으로 설계하면 유지보수 횟수를 줄이고 변화에 대응 가능.
장단점
- 장점: 데이터 일관성 유지, 유지보수 용이.
- 단점: 데이터 변경이 시스템 전체에 영향을 미침.
4. 프로세스 지향 방법과 데이터 지향 방법의 문제점
문제점
- 변경의 영향: 프로세스와 데이터가 분리되어 있어 한쪽이 바뀌면 다른 쪽에 영향을 미침.
- 프로그램 복잡도 증가: 함수와 데이터가 분리되어 있어 복잡성이 증가.
- 재사용의 어려움: 프로세스와 데이터가 분리된 구조로 인해 재사용이 어려움.
- 유지보수의 어려움: 복잡한 구조로 인해 유지보수가 쉽지 않음.
5. 객체 지향 방법
개요
- 정의: 기능이나 데이터 대신 객체가 중심이 되어 시스템을 설계하는 방법.
- 구성 요소: 객체, 클래스, 메서드.
특징
- 실세계 모델링: 실세계를 사람이 생각하는 방식으로 표현.
- 데이터 캡슐화: 데이터와 메서드를 객체로 묶어, 객체의 인터페이스만을 통해 데이터 접근.
- 유연성: 요구사항 변경에 유연하게 대처 가능.
- 확장성: 객체의 추가/삭제가 쉬워 확장성이 높음.
- 재사용성: 객체 단위로 재사용 가능.
- 추상화: 시스템 설계를 단순화하고, 추상화를 통해 생산성과 품질을 높임.
장단점
- 장점: 실세계 모델링, 데이터 캡슐화, 요구사항 변경에 유연한 대처, 확장성과 재사용성 높음.
- 단점: 초기 설계가 복잡할 수 있음.
6. 디자인 패턴
정의
- 디자인 패턴: 자주 사용하는 설계 형태를 정형화해서 이를 유형별로 설계 템플릿으로 만든 것.
- 목적: 반복되는 설계 문제를 해결할 수 있도록 체계적으로 정리된 해결책 제공, 소프트웨어 설계를 간소화하고, 코드의 재사용성을 높이며, 유지보수를 용이하게 함.
중요성
- 전문가의 노하우: 많은 개발자들이 경험을 통해 검증된 설계 지식을 추상화하여 일반화한 템플릿.
- 효율적 문제 해결: 설계 문제를 해결하는 데 도움을 주며, 코드의 견고성과 재사용성을 높임.
7. 디자인 패턴 사용의 장단점
장점
- 의사소통 원활: 디자인 패턴을 통해 개발자들 간의 원활한 의사소통이 가능.
- 구조 파악 용이: 디자인 패턴을 사용하면 소프트웨어 구조를 쉽게 파악할 수 있음.
- 재사용성: 미리 정의된 디자인 패턴을 사용하여 개발 시간을 단축.
- 설계 변경에 유연: 기능 추가나 환경 변화에 유연하게 대처 가능.
단점
- 구조적 설계에 부적합: 디자인 패턴은 주로 객체지향 설계/구현에 적합하며, 구조적 설계에는 적합하지 않음.
- 초기 투자 비용: 디자인 패턴을 사용하면 초기 투자 비용(시간과 노력)이 더 들 수 있음.
8. Code Complete의 9가지 휴리스틱
주요 내용
- 객체 식별: 시스템에서 사용할 객체를 식별.
- 일관된 추상화 적용: 일관된 추상화를 통해 설계의 명확성 유지.
- 캡슐화: 구현에서 결정할 상세 사항을 캡슐화.
- 상속보다 합성 사용: 상속보다 합성을 통해 유연한 설계.
- 정보 은닉: 정보를 감추고, 필요한 정보만 노출.
- 느슨한 결합, 강한 응집: 모듈 간의 결합은 느슨하게, 모듈 내부는 강하게 응집.
- 변경 부분 식별: 변경될 가능성이 높은 부분을 식별하고, 이를 설계에 반영.
- 디자인 패턴 사용: 적절한 디자인 패턴을 사용하여 설계.
- 테스트 용이성: 테스트하기 쉽게 설계.
9. 상속과 합성
상속 (Inheritance)
- 정의: 클래스가 다른 클래스의 속성과 메서드를 상속받아 사용하는 것.
- 장점: 코드 재사용성, 상위 클래스의 기능을 하위 클래스에서 사용 가능.
- 단점: 상위 클래스의 변경이 하위 클래스에 영향을 미칠 수 있음, 캡슐화를 깨뜨릴 수 있음.(is-a관계 이외에는 사용을 자제해야 한다)
합성 (Composition)
- 정의: 클래스가 다른 클래스의 인스턴스를 포함하여 사용하는 것.
- 장점: 재사용이 용이, 클래스 라이브러리 유지 간단, 캡슐화를 유지, 결합을 약하게 함, 런타임 바인딩 가능.
- 단점: 상속보다 구현이 복잡할 수 있음.
Gangs of Four (GoF) 패턴 요약
생성 패턴 (주상 객체 인스턴스화)
- 추상 팩토리, 팩토리, 빌더, 프로토타입, 싱글톤
구조 패턴 (객체 결합)
- 어댑터, 브리지, 컴포지트, 데코레이터, 퍼사드, 플라이웨이트, 프록시
행위 패턴 (객체 간 커뮤니케이션)
- 책임 체인, 커맨드, 인터프리터, 반복자 (Iterator), 중재자, 메멘토, 옵서버, 상태, 전략 (Strategy), 템플릿 메소드, 비지터
요약
- 목적: 너무 일반적이지도, 너무 구체적이지도 않은 형태로 소프트웨어 설계를 위한 지식이나 노하우를 공유.
- 에릭 감마, 리차드 헬름, 랄프 존슨, 존 블리시데스가 제안한 GoF 23개의 디자인 패턴이 설계 목적에 따라 구분됨.
10. 싱글톤 패턴 (Singleton Pattern)
정의
- 싱글톤 패턴: 클래스의 인스턴스를 하나만 생성하도록 제한하는 디자인 패턴.
- 목적: 특정 클래스의 객체가 오직 하나만 존재하도록 보장, 자원 낭비 방지.
구현 방법
- 생성자 private: 외부에서 생성자를 호출하지 못하도록 private으로 설정.
- static 인스턴스: 클래스 내부에 static으로 인스턴스를 선언.
- getInstance() 메서드: 인스턴스를 반환하는 public 메서드를 제공.
- 동기화: 멀티스레드 환경에서 안전하게 인스턴스를 반환하도록 동기화.
사용 예
- 난수 생성기: 난수를 생성하는 객체를 하나만 유지.
- 프린터 스풀러: 프린터에 출력할 데이터를 관리하는 객체를 하나만 유지.
- 점수 기록표: 점수를 기록하는 객체를 하나만 유지.
인터페이스의 개념
정의
- 인터페이스: 클래스가 구현해야 하는 메서드들의 집합을 정의하는 것. 기능의 선언과 기능의 구현을 분리
- 목적: 클래스들이 일관된 방식으로 특정 기능을 수행하도록 강제. 기능을 사용하는 통로
장점
- 일관성: 인터페이스를 구현함으로써 일관된 메서드 시그니처를 유지할 수 있음.
- 유연성: 인터페이스를 통해 다형성을 구현할 수 있어, 다양한 클래스들이 동일한 인터페이스를 구현하여 서로 교환 가능.
- 독립성: 인터페이스만 준수하면, 클래스의 구체적인 구현 방식과 관계없이 사용할 수 있음.
- 다중 상속 효과: 자바는 클래스의 다중 상속을 지원하지 않지만, 인터페이스를 통해 다중 상속의 효과를 얻을 수 있음.
// 인터페이스 정의
public interface Weapon {
void attack();
}
// 인터페이스 구현 클래스
public class Sword implements Weapon {
@Override
public void attack() {
System.out.println("칼 공격");
}
}
public class Knife implements Weapon {
@Override
public void attack() {
System.out.println("검 공격");
}
}
// 인터페이스 사용
public class GameCharacter {
private Weapon weapon;
// 무기 교환
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
// 공격
public void attack() {
if (weapon == null) {
System.out.println("맨손 공격");
} else {
weapon.attack();
}
}
}
// 메인 클래스
public class Main {
public static void main(String[] args) {
GameCharacter character = new GameCharacter();
character.setWeapon(new Sword());
character.attack(); // 출력: 칼 공격
character.setWeapon(new Knife());
character.attack(); // 출력: 검 공격
}
}
Comments 0