SlideShare uma empresa Scribd logo
1 de 66
박진호
 Pimpl 이디엄
 싱글톤과 팩토리 메서드
 프록시, 어댑터와 퍼사드
 옵저버
 내부의 구체적인 코드를 public 헤더 파일로
부터 완전히 숨김
 기본적으로 private 멤버 변수와 함수를 .cpp
파일에 위치 시킴
공개 인터페이스
Public:
Function1()
Function2()
Protected:
Function3()
Private:
Impl* pImpl 내부 구현
Public:
PrivateFuntion1()
PrivateFunction2()
PrivateData1
privateData2
pImpl 이디엄은 숨겨진 구현 클래스를 내부 포인터로 가리키는 공개
클래스를 말함
// autotimer.h
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include <string>
class AutoTimer
{
public:
/// Create a new timer object with a human readable name
explicit AutoTimer(const std::string &name);
/// On destruction, the timer reports how long it was alive
AutoTimer();
private:
// Return how long the object has been alive
double GetElapsed() const;
std::string mName;
#ifdef WIN32
DWORD mStartTime;
#else
struct timeval mStartTime;
#endif
// autotimer.h
#include <string>
class AutoTimer
{
public:
explicit AutoTimer(const std::string &name);
AutoTimer();
private:
class Impl;
Impl *mImpl;
};
#include "autotimer.h"
#include <iostream>
#if_WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
class AutoTimer::Impl
{
public:
double GetElapsed() const
{
#ifdef _WIN32
return (GetTickCount() - mStartTime) / 1e3;
#else
struct timeval end_time;
gettimeofday(&end_time, NULL);
double t1 = mStartTime.tv_usec / 1e6 + mStartTime.tv_sec;
double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec;
return t2-t1;
#endif
}
std::string mName;
#ifdef _WIN32
DWORD mStartTime;
#else
struct timeval mStartTime;
#endif
AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl())
{
mImpl->mName name;
#ifdef _WIN32
mImpl->mStartTime = GetTickCount();
#else
gettimeofday(&mImpl->mStartTime, NULL);
#endif
}
AutoTimer::AutoTimer()
{
std::cout << mImpl >mName << ": took " << mImpl >GetElapsed() << " secs" << std::endl;
delete mImpl;
mImpl = NULL;
}
AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl())
{
mImpl->mName name;
#ifdef _WIN32
mImpl->mStartTime = GetTickCount();
#else
gettimeofday(&mImpl->mStartTime, NULL);
#endif
}
AutoTimer::AutoTimer()
{
std::cout << mImpl >mName << ": took " << mImpl >GetElapsed() << " secs" << std::endl;
delete mImpl;
mImpl = NULL;
}
1. Private 멤버 변수만을 포함한다.
2. Private 멤버 변수와 함수를 포함한다.
3. Public 클래스의 모든 함수와 대응되는 함수
를 Impl 클래스에 구현한다.
 기본적으로 얕은 복사가 사용됨.
 다음의 2가지 선택사항을 취해 얕은 복사 시
예상치 못한 오류 발생 예방
 클래스를 복사할 수 없게 만듦
▪ Private으로 복사 생성자 선언 및 할당 연산자 선언
 깊은 복사 기능을 명시적으로 정의
 정보 은닉
 #define prive public
 #include “yourapi.h”
 #undef private
 의존성 제거
 Windows.h 및 sys/time.h에 대한 의존성 없앰
 빠른 컴파일
 Api 계층 구조가 줄어듦
 뛰어난 이진 호환성
 Pimpl 이디엄 포함한 객체의 크기는 절대 바뀌지 않음
 지연 할당
 Pimpl 클래스는 필요할 때 생성되기 때문에 네트워크 연결과
같은 제한된 또는 많은 비용이 드는 리소스를 사용할 때 유용
 Pimpl 구현 객체를 메모리에 할당하고 해제해야하는 문제.
 포인터의 크기 때문에 객체 크기 역시 늘어나서 모든 변수 접근에
필요한 간접 참조의 성능 문제 발생
 New와 delete 호출에 따른 추가적인 비용
▪ 빠른 Pimpl 이디엄(new와 delete 연산자를 오버로드 해서 적은 메모리를 사
용하도록 고정된 크기의 메모리 할당자를 사용하는 효율적인 메모리 사용 방
법)
 코드를 읽는 것, 디버깅 하는것도 어려워 짐.
 상수 함수 안에 있는 변수들은 분리된 객체 안에 존재하기 때문에
컴파일러는 이 변수들의 값 변화를 더 이상 감지할 수없음.
void PimpledObject::ConstMethod() const
{
mImpl->mName = "string changed by a const method";
}
 페이지 112 ~ 114 참고
 어떻게 싱글톤 객체를 할당할 것인가?
 언제 싱글톤 객체를 파괴 시킬 것인가?
 쓰레드 안정성을 지원하는 가?
 쭉정이(알맹이가 없는) 싱글턴을 사용하면
어떻게 되는가?
 발전된 형태의 전역 변수
 프로그램 상에서 하나의 인스턴스만 있고
두번째 인스턴스를 만들 수 없는 기능
 쓰임에 따라 최선의 방법들이 달라짐
 기본 생성자를 private에 선언
 외부에서 new로 객체 생성 불가
 Singleton* pObject = new Singleton();  컴파일 에러
 복사 생성자, 복사 대입연산자 도 private에 선언
 복사로 인한 생성 불가
 정의를 하지 않고 선언만 함
(정의가 있으면 멤버함수 혹은 프렌드 함수가 호출 할 수 있기 때문에 정의
하지 않음)
 복사 생성자
▪ Singleton object1( Singleton::GetInstance() );  컴파일 에러
 복사 대입 연산자
▪ Singleton& object1 = Singleton::GetInstance();
▪ Singleton& object2 = Singleton::GetInstance();
▪ object1 = object2;  컴파일 에러
 .h
 .cpp
 Static 클래스 멤버 변수는 static 전역 변수처럼 프로그램
시작 시 main() 함수 호출 이전에 초기화
 싱글톤 객체 사용하지 않더라도 무조건 생성되기 때문
에 비효율적
 정적 객체는 다른 전역객체의 생성자에서 참고하고 싶
은 경우 문제 발생 할 수 있음
 C++ 표준에서는 전역 객체들의 생성 순서에 대해 명확하게 정
의하고 있지 않기 때문
 Main() 함수가 실행 하기 전에만 생성되면 됨
 어떤 전역 객체의 생성자에서 위 싱글톤 객체를 참조하려고
할 경우 싱글톤 객체가 생성되기 전인 경우 문제 발생 할 수 있
음
 .h
 .cpp
 최초 GetInstace() 를 호출하는 시점에 객체가
생성
 한번도 해당 객체를 생성하지 않으면 객체 생
성 하지 않으므로 자원을 효율적으로 사용
 다른 전역 객체의 생성자에서 참조하는 것도
가능
 프로그램이 종료되는 순간 동적 객체는 자동으
로 해제되기 때문에 굳이 명시적으로 해제할
필요 없음
 프로그램을 종료하기 위해 exit() 가 수행하는 cleanup 과정 (C++ 기준)
1. 현재 thread의 thread storage duration 내에 있는 object 들을 모두
소멸 ( C++11 only)
2. static storage duration의 object들을 소멸
1. Static storage duration
2. Thread storage duration
3. Automatic storage duration
4. Dynamic storage duration
3. atexit 에 등록되어 있는 함수들을 호출
4. 모든C stream(stdin, stdout, stderr 등등) 과 tmpfile 에 의해 생성된
파일들을 비우고 닫음
5. 제어권이 host environment 로 넘어감
 두번째 싱글톤 객체가 반드시 프로그램 종료
시 반납해야 하는 외부 시스템 자원을 사용하
는 경우 사용
 싱글턴 객체를 이용하여, OS 리소스 를 만들고 해제
하지 않는다면 "리소스 릭:Resource Leak" 이 발생
 싱글턴 객체의 소멸자에 리소스 해제 기능을 놓고,
싱글턴 객체를 파괴 함 으로써 이러한 문제 해결
 Ateexit() 함수를 사용
 다른 전역 객체의 소멸자를 이용
 #include <stdlib.h>
 int atexit(void (*func)(void));
 함수 호출 성공 시 0, 실패 시 0 아닌 값 반환.
 반환형과 매개변수 형이 void로 선언된 함수의 이름이(주소 값이)
atexit함수의 인자로 전달
 인자로 전달된 함수가 프로그램 종료 시 자동으로 호출되며, 이렇게 자
동으로 호출되어야 할 함수는 32개 이상 등록할 수 있음.
 atexit 함수의 특성
 등록된 순서의 역순으로 호출
 atexit 함수를 통해서 등록된 함수는 프로그램이 정상적으로 종료될 때에만
호출
 .h
.cpp
 .h
.cpp
 명시적 해제 작업을 피하기 위해 static 지역 객
체 사용
1. 지역 static 객체는 전역 static 객체와 달리 해당 함수를
처음 호출 하는 시점에 초기화
2. 위 객체를 한번도 사용하지 않으면 생성되지 않음
3. Static 이므로 프로그램 종료 시 까지 객체가 유지
4. 종료시에는 자동으로 소멸자 호출
 로그 객체, 키보드 객체, 모니터 객체가 존재하며, 네번째 싱글톤으로 구성
(1)키보드 객체를 생성하고, 모니터 객체를 생성 하는 중 실패하여,
(2)로그 객체를 생성하여 로그를 찍음
(3)그리고 프로그램이 종료 작업에 들어 가게 됨.
 에러 상황
(4) 로그 객체는 먼저 삭제됨.
(5)키보드 객체를 파괴할 때, 실패하여,
(6)로그 객체를 이용해 로그를 찍으려 함
하지만, 로그 객체는 이미 파괴된 후이므로, 쭉정이 싱글톤에 접근하게 되어, 크래
쉬가 발생
 상황 분석
 static 을 이용하기 때문에, 스택 형태로 메모리에 올라와져 있어, 키보드 객체가 파괴되기 전 로
그 객체 부터 파괴.
 왜냐하면 로그 객체가 키보드 객체 후에 만들어졌기 때문
 네번째 싱글톤 객체를 다른 전역 객체의 소멸
자에서 사용하려고 하면 문제 발생
 C++ 표준에서는 전역 객체들의 생성 순서만 명시하
지 않은 것이 아니라 소멸 순서에 대해서도 명시해
놓지 않음
 어떤 전역 객체가 소멸자에서 저 싱글톤 객체를 사
용하려고 할 때 싱글톤 객체가 먼저 소멸했다면 문
제가 발생 (참조 무효화)
 싱글톤 참조 시 해당 객체의 소멸 여부를 파악
하고 만약 소멸했다면 되살림
 싱글턴의 파괴 시점을 조작
 Static 지역 변수의 특징
 메모리의 생성은 프로그램이 static 지역변수 가 포함된
함수를 호출해야 생성
 프로그램 종료 시점에 메모리 파괴가 일어난다 해도 그
공간은 빈 공간으로 남아 있음( 다른것으로 채워지지
않음)
 위 특징 사용.
 프로그램 종료 시점에 그 메모리 공간에 다시 쓰기 위
해 replacement new를 사용
 파괴 시점을 제어하기 위해 std::atexit함수 사용
 Replacement new
 이미 할당된 메모리 공간에 생성자만 호출
 일반 new처럼 사용하되 인자로 메모리가 할당되어있는 포인터를
넘겨줌
 내부적으로 void* operator new(size_t, void*) 원형의 new를 호출
 Ex)
 void* pBase = malloc(sizeof(CBase));
 new(pBase) CBase;
 메모리를 재할당 하지 않음
 기존 데이터가 그대로 남아있고, 생성자에서 초기화하는 데이터
만 초기화
 가상함수 테이블을 초기화
 메모리풀링 등에서 유용하게 사용
 .h
 .cpp
Static 객체의 생성/소멸 시점에 대해 정확히 파악해서 싱글톤 객체를 전
역 객체의 생성/ 소멸자에서 마구잡이로 참조하는 일이 없도록 주의해서
프로그래밍 해야함
 고려해야 할 사항
 싱글턴 객체의 생성 동기화
 고려해야 할 사항
 싱글턴 객체의 생성 동기화
 멀티 스레드 환경 지원 안함
 쓰레드A가 GetInstance() 함수 진입
 1번 조건 체크 하고 다음 줄 실행 전에 중지
 쓰레드 B가 GetInstance() 함수에 진입
 쓰레드 B는 s_pInstance가 NULL 이므로 1번 계속 진행.

 쓰레드 B는 2번 실행하여 객체 생성 후 호출자에게 instance 리턴
 쓰레드A는 다시 진행 됨. 2번이 다시 호출되어 또다른 인스턴스 생성
A쓰레드 B쓰레드
2번
1번
2번
1번
B쓰레드
널일 경우에만 락을 획득 하기 위함
위 조건 체크와 락을 얻을 때 사이에 다른 스
레드가 먼저 들어와서 pInstance를 초기화 할
수 있기 때문에 한번더 null 인지 체크
 s_pInstance = new LazySingleton(); 의미
 1. Singleton 객체를 담기 위한 메모리를 할당
 2. 할당된 메모리에 Singleton 객체를 생성
 3. s_pInstance가 할당된 메모리를 가리키도록 함
 컴파일러가 이 순서대로 수행되도록 제한하지
않음. 컴파일러는 때때로 스텝 2와 스텝 3사이의
순서를 바꾸기도 함
 A쓰레드에서 s_pInstance가 할당된 메모리
를 가리키도록 하고 그 후에 할당된 메모리
에 객체를 생성 해야 하는데 할당 전에
 B 쓰레드에서 싱글턴 객체를 바로 사용할 경
우 껍데기를 접근하여 문제 발생
 (싱글턴 객체는 메모리를 가리키기만 하고
실제 객체객체 생성은 안된 상황)
 Volatile 한정 지시자 사용
 volatile로 선언된 개체(변수, 메모리 위치, 코드)는
optimize 룰을 적용하지 말라.
 ( Objects declared as volatile are not used in certain
optimizations ( 출처 - MSDN ))
 컴파일러가 효율 등을 고려해 optimize 관점에서 코
드를 임의로 변경(의미 없는 코드 삭제나 실행 순서
변경)을 시키지 않음
 volatile로 선언된 개체는 메모리에 할당되고 작업 요
청시 직접(해당 주소에), 바로(효율을 위한 지연 없
이) 처리된다.
 volatile 키워드를 사용해야 할 곳이 있다면 C++11에
서는 atomic 변수를 사용
 C++11에서는 '서로 다른 스레드 간에 순서 관계가 정
의 되지 않은 메모리 읽기 쓰기 조작은 data race에
의한 알 수 없는 동작을 한다' 라고 되어 있음.
 즉 C++11에서 volatile 변수는 Memory Barrier 동작을
한다고 명시하지 않음
 메모리 바리어는 대부분 낮은 수준의 기계어에서 사
용되며 여러 장치가 공유하는 메모리를 사용하는 데
쓰임
 Lazy Instance 모델 대신 코드가 실행되는 시점,
main() 이 호출되기 전이나 뮤텍스 잠금으로
API가 초기화 시점에 초기화
 정적 초기화
static Singleton& foo = Singleton::GetInstance();
 명시적 API 초기화
VoidAPIInitialize()
{
Mutex mutex;
ScopredLock(&mutex);
Singleton::GetInstance();
}
 의존성 삽입
class MyClass
{
public:
MyClass() : mDatabase( new Database ("mydb, "localhost", "user", "pass"))
{}
private:
Database* mDatabase;
}
class MyClass
{
public:
MyClass(Database* db) : mDatabase(db)
{}
private:
Database* mDatabase;
}
 모노스테이트 패턴
 싱글톤의 문제는 전역 상태를 유지하고 접근하는데서 발생
// monostate.h
class MonoState
{
public:
int GetTheAnswer() const { return sAnswer; }
private:
static int sAnswer;
};
// monostate.cpp
int MonoState::sAnswer = 42;
 세션 문맥 사용
 C++ 생성자에서의 제약 사항
 결과 값 리턴 불가
 명명 규칙의 제약
 정적 형식의 객체 생성
 가상 생성자의 부재
 팩토리 메서드는 위 제약사항에 구애받지
않음
// renderer.h
#include <string>
class IRenderer
{
public:
virtual IRenderer() {}
virtual bool LoadScene(const std::string &filename) 0;
virtual void SetViewportSize(int w, int h) 0;
virtual void SetCameraPosition(double x, double y, double z) 0;
virtual void SetLookAt(double x, double y, double z) 0;
virtual void Render() 0;
};
// rendererfactory.h
#include "renderer.h"
#include <string>
class RendererFactory
{
public:
IRenderer *CreateRenderer(const std::string &type);
};
// rendererfactory.cpp
#include "rendererfactory.h"
#include "openglrenderer.h"
#include "directxrenderer.h"
#include "mesarenderer.h“
IRenderer *RendererFactory::CreateRenderer(const std::string &type)
{
if (type "opengl")
return new OpenGLRenderer();
if (type "directx")
return new DirectXRenderer();
if (type "mesa")
return new MesaRenderer();
return NULL;
 사용자가 원하는 타입의 인스턴스를 런타임
시에 생성하기 때문에 유연성 제공
 상속 클래스의 헤더 파일은 팩토리를 구현
하는 .cpp 파일에만 존재하며 public으로 선
언된 RenererFacory.h 파일에는 포함하지 않
음
 그러나 이것은 사용자에게 새로운 그래픽
처리기를 제공하지 못함.
 팩토리 메서드와 상속 클래스간의 연결 관
계를 느슨하게 만듦
 런타임시에 새로운 상속 클래스를 추가할
수 있도록 타입 이름을 객체 생성 콜백 함수
에 연결시키는 맵을 팩토리 클래스에서 사
용
// rendererfactory.h
#include "renderer.h"
#include <string>
#include <map>
class RendererFactory
{
public:
typedef IRenderer *(*CreateCallback)();
static void RegisterRenderer(const std::string &type, CreateCallback cb);
static void UnregisterRenderer(const std::string &type);
static IRenderer *CreateRenderer(const std::string &type);
private:
typedef std::map<std::string, CreateCallback> CallbackMap;
static CallbackMap mRenderers;
};
#include "rendererfactory.h"
// instantiate the static variable in RendererFactory
RendererFactory::CallbackMap RendererFactory::mRenderers;
void RendererFactory::RegisterRenderer(const std::string &type, CreateCallback cb)
{
mRenderers[type] cb;
}
void RendererFactory::UnregisterRenderer(const std::string &type)
{
mRenderers.erase(type);
}
IRenderer *RendererFactory::CreateRenderer(const std::string &type)
{
CallbackMap::iterator it mRenderers.find(type);
if (it ! mRenderers.end())
{
// call the creation callback to construct this derived type
return (it >second)();
}
return NULL;
}
class UserRenderer : public IRenderer
{
public:
UserRenderer() {}
bool LoadScene(const std::string &filename) { return true; }
void SetViewportSize(int w, int h) {}
void SetCameraPosition(double x, double y, double z) {}
void SetLookAt(double x, double y, double z) {}
void Render() { std::cout << "User Render" << std::endl; }
static IRenderer *Create() { return new UserRenderer(); }
};
int main(int, char **)
{
// register a new renderer
RendererFactory::RegisterRenderer("user", UserRenderer::Create);
// create an instance of our new renderer
IRenderer *r RendererFactory::CreateRenderer("user");
r->Render();
delete r;
return 0;
}
 한 클래스의 인터페이스를 클라이언트에서
사용하고자 하는 다른 인터페이스로 변환
어댑터를 이용하면 인터페이스 호환성 문제
때문에 같이 쓸 수 없는 클래스들을 연결해
서 쓸 수 있음.
public class Adapter implements target{
request(){
translatedRequest();
}
}
클라이언트와 어댑티는 서로 분리
서로 상대방에 대해서 전혀 모름.
어댑터에서 타겟 인터페이스를구현
어댑터는 어댑티로 구성
모든 요청은 어댑티에게 위임
public class Adapter implements target{
request(){
specificRequest();
}
}
객체 구성(Composition) 사용
어댑티의 어떤 서브클래스에 대해서도 어댑터
를 쓸 수 있다는 장점
클라이언트를 특정 구현이 아닌 인터페이스에 연결
- 여러 어댑터 사용 가능
- 타겟 인터페이스만 제대로 지키다면 다른 구현
추가 가능
다중상속을 사용해서 어댑
터를 어댑티와 타켓 클랙스
모두의 서브클래스로 만듦.
※ 자바에서는 실제로 동작하지 않는 코드입니다
public class Adapter extends Target, Adaptee{
public void request(){
specificRequest();
}
}
- 어댑티 전체는 다시 구현하지 않아도 됨
- 어댑티의 행동을 오버라이딩 가능
- 구성을 사용하기 때문에 그 서
브클래스에 대해서도 어댑터
역할을 할 수 있음
 어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공
퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있
음
클래스 다이어그램
1. 일대다 관계 (one-to-many)
• 상태를 저장하고 지배하는 것은 주제 객체.
• 옵저버는 여러 개가 있을 수 있지만,
주제 객체에서 상태가 바뀌었다는 것을 알려주기를
기다리는 주제에 의존 적인 성질을 가짐.
2. 의존성
1. 옵저버는 주제 객체가 데이터를 갱신해 주기를
기다리는 입장 이기 때문에 의존성을 가짐.
2. 이런 방식으로 인해
깔끔한 객체지향 디자인을 만들 수 있음.
update()
<interface>
Observer
regosterObserver() { … }
removeObserver() { … }
notifyObservers() { … }
getState( )
setState( )
ConcreateSubject
regosterObserver()
removeObserver()
notifyObservers()
<interface>
Subject
update()
//기타 해당 옵저버의 메소
드
ConcreateObserver
옵저버
주제
옵저버가 될 가능성
이 있는 객체는 해당
인터페이스 상속.
옵저버를
등록/탈퇴/공지 하는
기능
상태를 설정하는
메소드가 필요
• 옵저버 패턴
한 객체의 상태가 바뀌면 그 객체
에 의존하는 다른 객체들한테 연락
이 가고 자동으로 내용이 갱신되는
방식으로 일대다(one-to-many) 의
존성을 정의
 옵저버 패턴에서는 주제와 옵저버가 느슨하게 결합되어 있는
객체 디자인을 제공.
 주제가 옵저버에 대해 아는 것은 옵저버가 특정 인터페이스를
구현(implements) 한다는 것 뿐.
 옵저버는 언제든지 새로 추가할 수 있음
 새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경
할 필요가 없음.
 주제와 옵저버는 서로 독립적으로 재사용할 수 있음.
 주제나 옵저버가 바뀌더라도 서로한테 영향을 미치지 않음.
감사합니다

Mais conteúdo relacionado

Mais procurados

이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)MIN SEOK KOO
 
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)Yongha Yoo
 
동기화, 스케줄링
동기화, 스케줄링동기화, 스케줄링
동기화, 스케줄링xxbdxx
 
C++ Advanced 강의 4주차
 C++ Advanced 강의 4주차 C++ Advanced 강의 4주차
C++ Advanced 강의 4주차HyunJoon Park
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부quxn6
 
Swift3 typecasting nested_type
Swift3 typecasting nested_typeSwift3 typecasting nested_type
Swift3 typecasting nested_typeEunjoo Im
 
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initializationEunjoo Im
 
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)MIN SEOK KOO
 
Swift3 generic
Swift3 genericSwift3 generic
Swift3 genericEunjoo Im
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디quxn6
 
파이썬 함수 이해하기
파이썬 함수 이해하기 파이썬 함수 이해하기
파이썬 함수 이해하기 Yong Joon Moon
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4연우 김
 
Effective c++chapter1 and2
Effective c++chapter1 and2Effective c++chapter1 and2
Effective c++chapter1 and2성연 김
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)익성 조
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4성연 김
 
Effective c++chapter8
Effective c++chapter8Effective c++chapter8
Effective c++chapter8성연 김
 
0.javascript기본(~3일차내)
0.javascript기본(~3일차내)0.javascript기본(~3일차내)
0.javascript기본(~3일차내)Sung-hoon Ma
 

Mais procurados (20)

이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
이것이 자바다 Chap. 6 클래스(CLASS)(KOR)
 
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
 
동기화, 스케줄링
동기화, 스케줄링동기화, 스케줄링
동기화, 스케줄링
 
C++ Advanced 강의 4주차
 C++ Advanced 강의 4주차 C++ Advanced 강의 4주차
C++ Advanced 강의 4주차
 
이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부
 
Swift3 typecasting nested_type
Swift3 typecasting nested_typeSwift3 typecasting nested_type
Swift3 typecasting nested_type
 
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initialization
 
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
이것이 자바다 Chap.11 기본 API 클래스(java)(KOR)
 
Swift3 generic
Swift3 genericSwift3 generic
Swift3 generic
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디이펙티브 C++ 5,6 장 스터디
이펙티브 C++ 5,6 장 스터디
 
파이썬 함수 이해하기
파이썬 함수 이해하기 파이썬 함수 이해하기
파이썬 함수 이해하기
 
Anatomy of Realm
Anatomy of RealmAnatomy of Realm
Anatomy of Realm
 
Java lambda
Java lambdaJava lambda
Java lambda
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4
 
Effective c++chapter1 and2
Effective c++chapter1 and2Effective c++chapter1 and2
Effective c++chapter1 and2
 
이펙티브 C++ (7~9)
이펙티브 C++ (7~9)이펙티브 C++ (7~9)
이펙티브 C++ (7~9)
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4
 
Effective c++chapter8
Effective c++chapter8Effective c++chapter8
Effective c++chapter8
 
0.javascript기본(~3일차내)
0.javascript기본(~3일차내)0.javascript기본(~3일차내)
0.javascript기본(~3일차내)
 

Destaque

연결리스트 박진호
연결리스트 박진호연결리스트 박진호
연결리스트 박진호jinho park
 
Api design for c++ ch3 pattern
Api design for c++ ch3 patternApi design for c++ ch3 pattern
Api design for c++ ch3 patternjinho park
 
블랙보드 개발 중인 기능
블랙보드 개발 중인 기능블랙보드 개발 중인 기능
블랙보드 개발 중인 기능미나 최
 
Publish Subscriber messaging pattern
Publish Subscriber messaging patternPublish Subscriber messaging pattern
Publish Subscriber messaging patternShirish Bari
 
Team10:TenTen for blackboard
Team10:TenTen for blackboardTeam10:TenTen for blackboard
Team10:TenTen for blackboardJong-hoon Baek
 
Scalable system design patterns
Scalable system design patternsScalable system design patterns
Scalable system design patternsSteve Min
 
Design pattern study 6 command pattern
Design pattern study 6 command patternDesign pattern study 6 command pattern
Design pattern study 6 command patterndragor0123
 
Observer pattern dragor
Observer pattern dragorObserver pattern dragor
Observer pattern dragordragor0123
 
Design patterns 스터디 - Singleton 패턴
Design patterns 스터디 - Singleton 패턴Design patterns 스터디 - Singleton 패턴
Design patterns 스터디 - Singleton 패턴Hyunho-Cho
 
Design Pattern 3
Design Pattern 3Design Pattern 3
Design Pattern 3Daniel Lim
 
Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴Hyunho-Cho
 
Arquitetura da plataforma com o Biztalk Server
Arquitetura da plataforma com o Biztalk ServerArquitetura da plataforma com o Biztalk Server
Arquitetura da plataforma com o Biztalk ServerMarkus Christen
 
Publisher subscriber pattern
Publisher subscriber patternPublisher subscriber pattern
Publisher subscriber patternDaeMyung Kang
 
Node Js와 Redis를 사용한 구조화된 데이터
Node Js와 Redis를 사용한 구조화된 데이터Node Js와 Redis를 사용한 구조화된 데이터
Node Js와 Redis를 사용한 구조화된 데이터jinho park
 
Learn design pattern-1
Learn design pattern-1Learn design pattern-1
Learn design pattern-1Daniel Lim
 
Desing Pattern-2
Desing Pattern-2Desing Pattern-2
Desing Pattern-2Daniel Lim
 
Design pattern 4
Design pattern 4Design pattern 4
Design pattern 4Daniel Lim
 

Destaque (20)

Git
Git Git
Git
 
연결리스트 박진호
연결리스트 박진호연결리스트 박진호
연결리스트 박진호
 
Api design for c++ ch3 pattern
Api design for c++ ch3 patternApi design for c++ ch3 pattern
Api design for c++ ch3 pattern
 
블랙보드 개발 중인 기능
블랙보드 개발 중인 기능블랙보드 개발 중인 기능
블랙보드 개발 중인 기능
 
Publish Subscriber messaging pattern
Publish Subscriber messaging patternPublish Subscriber messaging pattern
Publish Subscriber messaging pattern
 
Pattern and EA
Pattern and EAPattern and EA
Pattern and EA
 
Team10:TenTen for blackboard
Team10:TenTen for blackboardTeam10:TenTen for blackboard
Team10:TenTen for blackboard
 
Scalable system design patterns
Scalable system design patternsScalable system design patterns
Scalable system design patterns
 
Design pattern study 6 command pattern
Design pattern study 6 command patternDesign pattern study 6 command pattern
Design pattern study 6 command pattern
 
Observer pattern dragor
Observer pattern dragorObserver pattern dragor
Observer pattern dragor
 
Design patterns 스터디 - Singleton 패턴
Design patterns 스터디 - Singleton 패턴Design patterns 스터디 - Singleton 패턴
Design patterns 스터디 - Singleton 패턴
 
Design Pattern 3
Design Pattern 3Design Pattern 3
Design Pattern 3
 
Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴Design patterns 스터디 -strategy패턴
Design patterns 스터디 -strategy패턴
 
Arquitetura da plataforma com o Biztalk Server
Arquitetura da plataforma com o Biztalk ServerArquitetura da plataforma com o Biztalk Server
Arquitetura da plataforma com o Biztalk Server
 
Publisher subscriber pattern
Publisher subscriber patternPublisher subscriber pattern
Publisher subscriber pattern
 
Node Js와 Redis를 사용한 구조화된 데이터
Node Js와 Redis를 사용한 구조화된 데이터Node Js와 Redis를 사용한 구조화된 데이터
Node Js와 Redis를 사용한 구조화된 데이터
 
Learn design pattern-1
Learn design pattern-1Learn design pattern-1
Learn design pattern-1
 
Desing Pattern-2
Desing Pattern-2Desing Pattern-2
Desing Pattern-2
 
4. publish / subscribe
4. publish / subscribe4. publish / subscribe
4. publish / subscribe
 
Design pattern 4
Design pattern 4Design pattern 4
Design pattern 4
 

Semelhante a Api design for c++ pattern

Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장 Shin heemin
 
Effective c++ Chapter1,2
Effective c++ Chapter1,2Effective c++ Chapter1,2
Effective c++ Chapter1,2문익 장
 
Effective c++ 1,2
Effective c++ 1,2Effective c++ 1,2
Effective c++ 1,2세빈 정
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinDong Chan Shin
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Nam Hyeonuk
 
모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디quxn6
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심흥배 최
 
Java 강의자료 ed11
Java 강의자료 ed11Java 강의자료 ed11
Java 강의자료 ed11hungrok
 
모어이펙티브 C++ 3,4장 예외, 효율 스터디
모어이펙티브 C++ 3,4장 예외, 효율 스터디모어이펙티브 C++ 3,4장 예외, 효율 스터디
모어이펙티브 C++ 3,4장 예외, 효율 스터디quxn6
 
More Effective C++ 4주차
More Effective C++ 4주차More Effective C++ 4주차
More Effective C++ 4주차Injae Lee
 
[Gpg2권]1.1 c++ 게임의 최적화
[Gpg2권]1.1 c++ 게임의 최적화[Gpg2권]1.1 c++ 게임의 최적화
[Gpg2권]1.1 c++ 게임의 최적화KyeongWon Koo
 
Effective C++ Chapter 3 Summary
Effective C++ Chapter 3 SummaryEffective C++ Chapter 3 Summary
Effective C++ Chapter 3 SummarySeungYeonChoi10
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3suitzero
 
Tcpl 14장 예외처리
Tcpl 14장 예외처리Tcpl 14장 예외처리
Tcpl 14장 예외처리재정 이
 
04 안드로이드 응용프로그램의 구조
04 안드로이드 응용프로그램의 구조04 안드로이드 응용프로그램의 구조
04 안드로이드 응용프로그램의 구조Wanbok Choi
 
Windows via c++ part 1
Windows via c++ part 1Windows via c++ part 1
Windows via c++ part 1Shin heemin
 
HolubOnPatterns/chapter2_2
HolubOnPatterns/chapter2_2HolubOnPatterns/chapter2_2
HolubOnPatterns/chapter2_2SeungHyun Hwang
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinDong Chan Shin
 

Semelhante a Api design for c++ pattern (20)

Effective c++ 1~8장
Effective c++ 1~8장 Effective c++ 1~8장
Effective c++ 1~8장
 
Effective c++ Chapter1,2
Effective c++ Chapter1,2Effective c++ Chapter1,2
Effective c++ Chapter1,2
 
Effective c++ 1,2
Effective c++ 1,2Effective c++ 1,2
Effective c++ 1,2
 
MEC++ 5
MEC++ 5MEC++ 5
MEC++ 5
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshin
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약
 
모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디모어 이펙티브 c++ 5장 스터디
모어 이펙티브 c++ 5장 스터디
 
Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심Modern C++ 프로그래머를 위한 CPP11/14 핵심
Modern C++ 프로그래머를 위한 CPP11/14 핵심
 
Java 강의자료 ed11
Java 강의자료 ed11Java 강의자료 ed11
Java 강의자료 ed11
 
모어이펙티브 C++ 3,4장 예외, 효율 스터디
모어이펙티브 C++ 3,4장 예외, 효율 스터디모어이펙티브 C++ 3,4장 예외, 효율 스터디
모어이펙티브 C++ 3,4장 예외, 효율 스터디
 
More Effective C++ 4주차
More Effective C++ 4주차More Effective C++ 4주차
More Effective C++ 4주차
 
[Gpg2권]1.1 c++ 게임의 최적화
[Gpg2권]1.1 c++ 게임의 최적화[Gpg2권]1.1 c++ 게임의 최적화
[Gpg2권]1.1 c++ 게임의 최적화
 
Effective C++ Chapter 3 Summary
Effective C++ Chapter 3 SummaryEffective C++ Chapter 3 Summary
Effective C++ Chapter 3 Summary
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3
 
Tcpl 14장 예외처리
Tcpl 14장 예외처리Tcpl 14장 예외처리
Tcpl 14장 예외처리
 
04 안드로이드 응용프로그램의 구조
04 안드로이드 응용프로그램의 구조04 안드로이드 응용프로그램의 구조
04 안드로이드 응용프로그램의 구조
 
Windows via c++ part 1
Windows via c++ part 1Windows via c++ part 1
Windows via c++ part 1
 
HolubOnPatterns/chapter2_2
HolubOnPatterns/chapter2_2HolubOnPatterns/chapter2_2
HolubOnPatterns/chapter2_2
 
More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshin
 

Api design for c++ pattern

  • 2.  Pimpl 이디엄  싱글톤과 팩토리 메서드  프록시, 어댑터와 퍼사드  옵저버
  • 3.  내부의 구체적인 코드를 public 헤더 파일로 부터 완전히 숨김  기본적으로 private 멤버 변수와 함수를 .cpp 파일에 위치 시킴
  • 4. 공개 인터페이스 Public: Function1() Function2() Protected: Function3() Private: Impl* pImpl 내부 구현 Public: PrivateFuntion1() PrivateFunction2() PrivateData1 privateData2 pImpl 이디엄은 숨겨진 구현 클래스를 내부 포인터로 가리키는 공개 클래스를 말함
  • 5. // autotimer.h #ifdef WIN32 #include <windows.h> #else #include <sys/time.h> #endif #include <string> class AutoTimer { public: /// Create a new timer object with a human readable name explicit AutoTimer(const std::string &name); /// On destruction, the timer reports how long it was alive AutoTimer(); private: // Return how long the object has been alive double GetElapsed() const; std::string mName; #ifdef WIN32 DWORD mStartTime; #else struct timeval mStartTime; #endif
  • 6. // autotimer.h #include <string> class AutoTimer { public: explicit AutoTimer(const std::string &name); AutoTimer(); private: class Impl; Impl *mImpl; };
  • 7. #include "autotimer.h" #include <iostream> #if_WIN32 #include <windows.h> #else #include <sys/time.h> #endif class AutoTimer::Impl { public: double GetElapsed() const { #ifdef _WIN32 return (GetTickCount() - mStartTime) / 1e3; #else struct timeval end_time; gettimeofday(&end_time, NULL); double t1 = mStartTime.tv_usec / 1e6 + mStartTime.tv_sec; double t2 = end_time.tv_usec / 1e6 + end_time.tv_sec; return t2-t1; #endif } std::string mName; #ifdef _WIN32 DWORD mStartTime; #else struct timeval mStartTime; #endif
  • 8. AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl()) { mImpl->mName name; #ifdef _WIN32 mImpl->mStartTime = GetTickCount(); #else gettimeofday(&mImpl->mStartTime, NULL); #endif } AutoTimer::AutoTimer() { std::cout << mImpl >mName << ": took " << mImpl >GetElapsed() << " secs" << std::endl; delete mImpl; mImpl = NULL; }
  • 9. AutoTimer::AutoTimer(const std::string &name) : mImpl(new AutoTimer::Impl()) { mImpl->mName name; #ifdef _WIN32 mImpl->mStartTime = GetTickCount(); #else gettimeofday(&mImpl->mStartTime, NULL); #endif } AutoTimer::AutoTimer() { std::cout << mImpl >mName << ": took " << mImpl >GetElapsed() << " secs" << std::endl; delete mImpl; mImpl = NULL; }
  • 10. 1. Private 멤버 변수만을 포함한다. 2. Private 멤버 변수와 함수를 포함한다. 3. Public 클래스의 모든 함수와 대응되는 함수 를 Impl 클래스에 구현한다.
  • 11.  기본적으로 얕은 복사가 사용됨.  다음의 2가지 선택사항을 취해 얕은 복사 시 예상치 못한 오류 발생 예방  클래스를 복사할 수 없게 만듦 ▪ Private으로 복사 생성자 선언 및 할당 연산자 선언  깊은 복사 기능을 명시적으로 정의
  • 12.  정보 은닉  #define prive public  #include “yourapi.h”  #undef private  의존성 제거  Windows.h 및 sys/time.h에 대한 의존성 없앰  빠른 컴파일  Api 계층 구조가 줄어듦  뛰어난 이진 호환성  Pimpl 이디엄 포함한 객체의 크기는 절대 바뀌지 않음  지연 할당  Pimpl 클래스는 필요할 때 생성되기 때문에 네트워크 연결과 같은 제한된 또는 많은 비용이 드는 리소스를 사용할 때 유용
  • 13.  Pimpl 구현 객체를 메모리에 할당하고 해제해야하는 문제.  포인터의 크기 때문에 객체 크기 역시 늘어나서 모든 변수 접근에 필요한 간접 참조의 성능 문제 발생  New와 delete 호출에 따른 추가적인 비용 ▪ 빠른 Pimpl 이디엄(new와 delete 연산자를 오버로드 해서 적은 메모리를 사 용하도록 고정된 크기의 메모리 할당자를 사용하는 효율적인 메모리 사용 방 법)  코드를 읽는 것, 디버깅 하는것도 어려워 짐.  상수 함수 안에 있는 변수들은 분리된 객체 안에 존재하기 때문에 컴파일러는 이 변수들의 값 변화를 더 이상 감지할 수없음. void PimpledObject::ConstMethod() const { mImpl->mName = "string changed by a const method"; }
  • 14.  페이지 112 ~ 114 참고
  • 15.  어떻게 싱글톤 객체를 할당할 것인가?  언제 싱글톤 객체를 파괴 시킬 것인가?  쓰레드 안정성을 지원하는 가?  쭉정이(알맹이가 없는) 싱글턴을 사용하면 어떻게 되는가?
  • 16.  발전된 형태의 전역 변수  프로그램 상에서 하나의 인스턴스만 있고 두번째 인스턴스를 만들 수 없는 기능  쓰임에 따라 최선의 방법들이 달라짐
  • 17.  기본 생성자를 private에 선언  외부에서 new로 객체 생성 불가  Singleton* pObject = new Singleton();  컴파일 에러  복사 생성자, 복사 대입연산자 도 private에 선언  복사로 인한 생성 불가  정의를 하지 않고 선언만 함 (정의가 있으면 멤버함수 혹은 프렌드 함수가 호출 할 수 있기 때문에 정의 하지 않음)  복사 생성자 ▪ Singleton object1( Singleton::GetInstance() );  컴파일 에러  복사 대입 연산자 ▪ Singleton& object1 = Singleton::GetInstance(); ▪ Singleton& object2 = Singleton::GetInstance(); ▪ object1 = object2;  컴파일 에러
  • 19.  Static 클래스 멤버 변수는 static 전역 변수처럼 프로그램 시작 시 main() 함수 호출 이전에 초기화  싱글톤 객체 사용하지 않더라도 무조건 생성되기 때문 에 비효율적  정적 객체는 다른 전역객체의 생성자에서 참고하고 싶 은 경우 문제 발생 할 수 있음  C++ 표준에서는 전역 객체들의 생성 순서에 대해 명확하게 정 의하고 있지 않기 때문  Main() 함수가 실행 하기 전에만 생성되면 됨  어떤 전역 객체의 생성자에서 위 싱글톤 객체를 참조하려고 할 경우 싱글톤 객체가 생성되기 전인 경우 문제 발생 할 수 있 음
  • 21.  최초 GetInstace() 를 호출하는 시점에 객체가 생성  한번도 해당 객체를 생성하지 않으면 객체 생 성 하지 않으므로 자원을 효율적으로 사용  다른 전역 객체의 생성자에서 참조하는 것도 가능  프로그램이 종료되는 순간 동적 객체는 자동으 로 해제되기 때문에 굳이 명시적으로 해제할 필요 없음
  • 22.  프로그램을 종료하기 위해 exit() 가 수행하는 cleanup 과정 (C++ 기준) 1. 현재 thread의 thread storage duration 내에 있는 object 들을 모두 소멸 ( C++11 only) 2. static storage duration의 object들을 소멸 1. Static storage duration 2. Thread storage duration 3. Automatic storage duration 4. Dynamic storage duration 3. atexit 에 등록되어 있는 함수들을 호출 4. 모든C stream(stdin, stdout, stderr 등등) 과 tmpfile 에 의해 생성된 파일들을 비우고 닫음 5. 제어권이 host environment 로 넘어감
  • 23.  두번째 싱글톤 객체가 반드시 프로그램 종료 시 반납해야 하는 외부 시스템 자원을 사용하 는 경우 사용  싱글턴 객체를 이용하여, OS 리소스 를 만들고 해제 하지 않는다면 "리소스 릭:Resource Leak" 이 발생  싱글턴 객체의 소멸자에 리소스 해제 기능을 놓고, 싱글턴 객체를 파괴 함 으로써 이러한 문제 해결  Ateexit() 함수를 사용  다른 전역 객체의 소멸자를 이용
  • 24.  #include <stdlib.h>  int atexit(void (*func)(void));  함수 호출 성공 시 0, 실패 시 0 아닌 값 반환.  반환형과 매개변수 형이 void로 선언된 함수의 이름이(주소 값이) atexit함수의 인자로 전달  인자로 전달된 함수가 프로그램 종료 시 자동으로 호출되며, 이렇게 자 동으로 호출되어야 할 함수는 32개 이상 등록할 수 있음.  atexit 함수의 특성  등록된 순서의 역순으로 호출  atexit 함수를 통해서 등록된 함수는 프로그램이 정상적으로 종료될 때에만 호출
  • 27.  명시적 해제 작업을 피하기 위해 static 지역 객 체 사용 1. 지역 static 객체는 전역 static 객체와 달리 해당 함수를 처음 호출 하는 시점에 초기화 2. 위 객체를 한번도 사용하지 않으면 생성되지 않음 3. Static 이므로 프로그램 종료 시 까지 객체가 유지 4. 종료시에는 자동으로 소멸자 호출
  • 28.  로그 객체, 키보드 객체, 모니터 객체가 존재하며, 네번째 싱글톤으로 구성 (1)키보드 객체를 생성하고, 모니터 객체를 생성 하는 중 실패하여, (2)로그 객체를 생성하여 로그를 찍음 (3)그리고 프로그램이 종료 작업에 들어 가게 됨.  에러 상황 (4) 로그 객체는 먼저 삭제됨. (5)키보드 객체를 파괴할 때, 실패하여, (6)로그 객체를 이용해 로그를 찍으려 함 하지만, 로그 객체는 이미 파괴된 후이므로, 쭉정이 싱글톤에 접근하게 되어, 크래 쉬가 발생  상황 분석  static 을 이용하기 때문에, 스택 형태로 메모리에 올라와져 있어, 키보드 객체가 파괴되기 전 로 그 객체 부터 파괴.  왜냐하면 로그 객체가 키보드 객체 후에 만들어졌기 때문
  • 29.  네번째 싱글톤 객체를 다른 전역 객체의 소멸 자에서 사용하려고 하면 문제 발생  C++ 표준에서는 전역 객체들의 생성 순서만 명시하 지 않은 것이 아니라 소멸 순서에 대해서도 명시해 놓지 않음  어떤 전역 객체가 소멸자에서 저 싱글톤 객체를 사 용하려고 할 때 싱글톤 객체가 먼저 소멸했다면 문 제가 발생 (참조 무효화)
  • 30.  싱글톤 참조 시 해당 객체의 소멸 여부를 파악 하고 만약 소멸했다면 되살림  싱글턴의 파괴 시점을 조작
  • 31.  Static 지역 변수의 특징  메모리의 생성은 프로그램이 static 지역변수 가 포함된 함수를 호출해야 생성  프로그램 종료 시점에 메모리 파괴가 일어난다 해도 그 공간은 빈 공간으로 남아 있음( 다른것으로 채워지지 않음)  위 특징 사용.  프로그램 종료 시점에 그 메모리 공간에 다시 쓰기 위 해 replacement new를 사용  파괴 시점을 제어하기 위해 std::atexit함수 사용
  • 32.  Replacement new  이미 할당된 메모리 공간에 생성자만 호출  일반 new처럼 사용하되 인자로 메모리가 할당되어있는 포인터를 넘겨줌  내부적으로 void* operator new(size_t, void*) 원형의 new를 호출  Ex)  void* pBase = malloc(sizeof(CBase));  new(pBase) CBase;  메모리를 재할당 하지 않음  기존 데이터가 그대로 남아있고, 생성자에서 초기화하는 데이터 만 초기화  가상함수 테이블을 초기화  메모리풀링 등에서 유용하게 사용
  • 34.  .cpp Static 객체의 생성/소멸 시점에 대해 정확히 파악해서 싱글톤 객체를 전 역 객체의 생성/ 소멸자에서 마구잡이로 참조하는 일이 없도록 주의해서 프로그래밍 해야함
  • 35.  고려해야 할 사항  싱글턴 객체의 생성 동기화
  • 36.  고려해야 할 사항  싱글턴 객체의 생성 동기화
  • 37.  멀티 스레드 환경 지원 안함
  • 38.  쓰레드A가 GetInstance() 함수 진입  1번 조건 체크 하고 다음 줄 실행 전에 중지  쓰레드 B가 GetInstance() 함수에 진입  쓰레드 B는 s_pInstance가 NULL 이므로 1번 계속 진행.   쓰레드 B는 2번 실행하여 객체 생성 후 호출자에게 instance 리턴  쓰레드A는 다시 진행 됨. 2번이 다시 호출되어 또다른 인스턴스 생성 A쓰레드 B쓰레드 2번 1번 2번 1번
  • 40. 널일 경우에만 락을 획득 하기 위함 위 조건 체크와 락을 얻을 때 사이에 다른 스 레드가 먼저 들어와서 pInstance를 초기화 할 수 있기 때문에 한번더 null 인지 체크
  • 41.  s_pInstance = new LazySingleton(); 의미  1. Singleton 객체를 담기 위한 메모리를 할당  2. 할당된 메모리에 Singleton 객체를 생성  3. s_pInstance가 할당된 메모리를 가리키도록 함  컴파일러가 이 순서대로 수행되도록 제한하지 않음. 컴파일러는 때때로 스텝 2와 스텝 3사이의 순서를 바꾸기도 함
  • 42.  A쓰레드에서 s_pInstance가 할당된 메모리 를 가리키도록 하고 그 후에 할당된 메모리 에 객체를 생성 해야 하는데 할당 전에  B 쓰레드에서 싱글턴 객체를 바로 사용할 경 우 껍데기를 접근하여 문제 발생  (싱글턴 객체는 메모리를 가리키기만 하고 실제 객체객체 생성은 안된 상황)
  • 43.  Volatile 한정 지시자 사용
  • 44.  volatile로 선언된 개체(변수, 메모리 위치, 코드)는 optimize 룰을 적용하지 말라.  ( Objects declared as volatile are not used in certain optimizations ( 출처 - MSDN ))  컴파일러가 효율 등을 고려해 optimize 관점에서 코 드를 임의로 변경(의미 없는 코드 삭제나 실행 순서 변경)을 시키지 않음  volatile로 선언된 개체는 메모리에 할당되고 작업 요 청시 직접(해당 주소에), 바로(효율을 위한 지연 없 이) 처리된다.
  • 45.  volatile 키워드를 사용해야 할 곳이 있다면 C++11에 서는 atomic 변수를 사용  C++11에서는 '서로 다른 스레드 간에 순서 관계가 정 의 되지 않은 메모리 읽기 쓰기 조작은 data race에 의한 알 수 없는 동작을 한다' 라고 되어 있음.  즉 C++11에서 volatile 변수는 Memory Barrier 동작을 한다고 명시하지 않음  메모리 바리어는 대부분 낮은 수준의 기계어에서 사 용되며 여러 장치가 공유하는 메모리를 사용하는 데 쓰임
  • 46.
  • 47.  Lazy Instance 모델 대신 코드가 실행되는 시점, main() 이 호출되기 전이나 뮤텍스 잠금으로 API가 초기화 시점에 초기화  정적 초기화 static Singleton& foo = Singleton::GetInstance();  명시적 API 초기화 VoidAPIInitialize() { Mutex mutex; ScopredLock(&mutex); Singleton::GetInstance(); }
  • 48.  의존성 삽입 class MyClass { public: MyClass() : mDatabase( new Database ("mydb, "localhost", "user", "pass")) {} private: Database* mDatabase; } class MyClass { public: MyClass(Database* db) : mDatabase(db) {} private: Database* mDatabase; }
  • 49.  모노스테이트 패턴  싱글톤의 문제는 전역 상태를 유지하고 접근하는데서 발생 // monostate.h class MonoState { public: int GetTheAnswer() const { return sAnswer; } private: static int sAnswer; }; // monostate.cpp int MonoState::sAnswer = 42;  세션 문맥 사용
  • 50.  C++ 생성자에서의 제약 사항  결과 값 리턴 불가  명명 규칙의 제약  정적 형식의 객체 생성  가상 생성자의 부재  팩토리 메서드는 위 제약사항에 구애받지 않음
  • 51. // renderer.h #include <string> class IRenderer { public: virtual IRenderer() {} virtual bool LoadScene(const std::string &filename) 0; virtual void SetViewportSize(int w, int h) 0; virtual void SetCameraPosition(double x, double y, double z) 0; virtual void SetLookAt(double x, double y, double z) 0; virtual void Render() 0; };
  • 52. // rendererfactory.h #include "renderer.h" #include <string> class RendererFactory { public: IRenderer *CreateRenderer(const std::string &type); }; // rendererfactory.cpp #include "rendererfactory.h" #include "openglrenderer.h" #include "directxrenderer.h" #include "mesarenderer.h“ IRenderer *RendererFactory::CreateRenderer(const std::string &type) { if (type "opengl") return new OpenGLRenderer(); if (type "directx") return new DirectXRenderer(); if (type "mesa") return new MesaRenderer(); return NULL;
  • 53.  사용자가 원하는 타입의 인스턴스를 런타임 시에 생성하기 때문에 유연성 제공  상속 클래스의 헤더 파일은 팩토리를 구현 하는 .cpp 파일에만 존재하며 public으로 선 언된 RenererFacory.h 파일에는 포함하지 않 음  그러나 이것은 사용자에게 새로운 그래픽 처리기를 제공하지 못함.
  • 54.  팩토리 메서드와 상속 클래스간의 연결 관 계를 느슨하게 만듦  런타임시에 새로운 상속 클래스를 추가할 수 있도록 타입 이름을 객체 생성 콜백 함수 에 연결시키는 맵을 팩토리 클래스에서 사 용
  • 55. // rendererfactory.h #include "renderer.h" #include <string> #include <map> class RendererFactory { public: typedef IRenderer *(*CreateCallback)(); static void RegisterRenderer(const std::string &type, CreateCallback cb); static void UnregisterRenderer(const std::string &type); static IRenderer *CreateRenderer(const std::string &type); private: typedef std::map<std::string, CreateCallback> CallbackMap; static CallbackMap mRenderers; };
  • 56. #include "rendererfactory.h" // instantiate the static variable in RendererFactory RendererFactory::CallbackMap RendererFactory::mRenderers; void RendererFactory::RegisterRenderer(const std::string &type, CreateCallback cb) { mRenderers[type] cb; } void RendererFactory::UnregisterRenderer(const std::string &type) { mRenderers.erase(type); } IRenderer *RendererFactory::CreateRenderer(const std::string &type) { CallbackMap::iterator it mRenderers.find(type); if (it ! mRenderers.end()) { // call the creation callback to construct this derived type return (it >second)(); } return NULL; }
  • 57. class UserRenderer : public IRenderer { public: UserRenderer() {} bool LoadScene(const std::string &filename) { return true; } void SetViewportSize(int w, int h) {} void SetCameraPosition(double x, double y, double z) {} void SetLookAt(double x, double y, double z) {} void Render() { std::cout << "User Render" << std::endl; } static IRenderer *Create() { return new UserRenderer(); } }; int main(int, char **) { // register a new renderer RendererFactory::RegisterRenderer("user", UserRenderer::Create); // create an instance of our new renderer IRenderer *r RendererFactory::CreateRenderer("user"); r->Render(); delete r; return 0; }
  • 58.  한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환 어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해 서 쓸 수 있음.
  • 59. public class Adapter implements target{ request(){ translatedRequest(); } } 클라이언트와 어댑티는 서로 분리 서로 상대방에 대해서 전혀 모름.
  • 60. 어댑터에서 타겟 인터페이스를구현 어댑터는 어댑티로 구성 모든 요청은 어댑티에게 위임 public class Adapter implements target{ request(){ specificRequest(); } } 객체 구성(Composition) 사용 어댑티의 어떤 서브클래스에 대해서도 어댑터 를 쓸 수 있다는 장점 클라이언트를 특정 구현이 아닌 인터페이스에 연결 - 여러 어댑터 사용 가능 - 타겟 인터페이스만 제대로 지키다면 다른 구현 추가 가능
  • 61. 다중상속을 사용해서 어댑 터를 어댑티와 타켓 클랙스 모두의 서브클래스로 만듦. ※ 자바에서는 실제로 동작하지 않는 코드입니다 public class Adapter extends Target, Adaptee{ public void request(){ specificRequest(); } }
  • 62. - 어댑티 전체는 다시 구현하지 않아도 됨 - 어댑티의 행동을 오버라이딩 가능 - 구성을 사용하기 때문에 그 서 브클래스에 대해서도 어댑터 역할을 할 수 있음
  • 63.  어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공 퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있 음
  • 64. 클래스 다이어그램 1. 일대다 관계 (one-to-many) • 상태를 저장하고 지배하는 것은 주제 객체. • 옵저버는 여러 개가 있을 수 있지만, 주제 객체에서 상태가 바뀌었다는 것을 알려주기를 기다리는 주제에 의존 적인 성질을 가짐. 2. 의존성 1. 옵저버는 주제 객체가 데이터를 갱신해 주기를 기다리는 입장 이기 때문에 의존성을 가짐. 2. 이런 방식으로 인해 깔끔한 객체지향 디자인을 만들 수 있음. update() <interface> Observer regosterObserver() { … } removeObserver() { … } notifyObservers() { … } getState( ) setState( ) ConcreateSubject regosterObserver() removeObserver() notifyObservers() <interface> Subject update() //기타 해당 옵저버의 메소 드 ConcreateObserver 옵저버 주제 옵저버가 될 가능성 이 있는 객체는 해당 인터페이스 상속. 옵저버를 등록/탈퇴/공지 하는 기능 상태를 설정하는 메소드가 필요 • 옵저버 패턴 한 객체의 상태가 바뀌면 그 객체 에 의존하는 다른 객체들한테 연락 이 가고 자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의 존성을 정의
  • 65.  옵저버 패턴에서는 주제와 옵저버가 느슨하게 결합되어 있는 객체 디자인을 제공.  주제가 옵저버에 대해 아는 것은 옵저버가 특정 인터페이스를 구현(implements) 한다는 것 뿐.  옵저버는 언제든지 새로 추가할 수 있음  새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경 할 필요가 없음.  주제와 옵저버는 서로 독립적으로 재사용할 수 있음.  주제나 옵저버가 바뀌더라도 서로한테 영향을 미치지 않음.