본문 바로가기
Programming/c++ Design Pattern

[C++ Design Pattern] Flyweight

by 드가보자 2023. 11. 30.

Flyweight 기법은 => 객체의 인스턴스를 공유해서 메모리 사용을 최적화 하는 기법이다.

걍 자원을 공유한다고 생각하면 될 것 같다.

#include <iostream>
#include <string>
#include <map>

class Image
{
	std::string image_url;
public:
	Image(const std::string& url) : image_url(url)
	{
		std::cout << url << " Downloading..." << std::endl;
	}
	void draw() { std::cout << "Draw " << image_url << std::endl; }
};

int main()
{
	Image* img1 = new Image("www.naver.com/a.png");
	img1->draw();

	std::cout <<"img1의 주소값은 "<< imㅁg1 << std::endl;

	Image* img2 = new Image("www.naver.com/a.png");
	img2->draw();
	std::cout << "img2의 주소값은 " << img2 << std::endl;

}

 

Image class를 만들고 string => image_url을 멤버 객체로 가진다. 그리고 생성자와 Draw하는 듯한 멤버 함수를 구현해준다.

main 함수에서 보면 

new Image("www.naver.com/a.png") <= 동일한 url을 두 번 사용해서 똑같은 객체가 두 번이나 생성되게 되는 것이다. 

이런 부분이 지금 메모리가 낭비된다는거다 , 굳이 한 번만 만들어지면되는 인스턴스인데..

실행해보면

img1의 주소값과 img2의 주소값이 확실히 다른 것을 볼 수 있다.

 

이를 해결하기 위해서는 생성자의 접근 제어 지시자를 private으로 바꾸고, 

public 함수에서 생성자를 호출해주는 방식으로 진행한다. => 대신 이미 만들어진 객체인지 검증하는 Step은 있겠지만

#include <iostream>
#include <string>
#include <map>

class Image
{
	std::string image_url;
	Image(const std::string& url) : image_url(url)
	{
		std::cout << url << " Downloading..." << std::endl;
	}

public:
	void draw() { std::cout << "Draw " << image_url << std::endl; }

	static std::map<std::string, Image*> image_map;
	static Image* create(const std::string& url)
	{
		Image* img = nullptr;

		auto it = image_map.find(url);

		if (it == image_map.end())
		{
			img = new Image(url);
			image_map[url] = img;
		}
		else img = it->second; 
		return img;
	}
};

std::map<std::string, Image*> Image::image_map;

int main()
{
	Image* img1 = Image::create("www.naver.com/a.png");
	img1->draw();

	Image* img2 = Image::create("www.naver.com/a.png");
	img2->draw();

	std::cout << img1 << std::endl;
	std::cout << img2 << std::endl;
}

 

Private 부분에 Image 생성자를 넘기고, static Image* create 함수를 만든다.

여기서 static map 을 만들어서 [ "url정보", iamge pointer] 로 관리할 것인데, 이미 존재하는 url의 값이라면 

auto it = image_map.find(url) 시에 image_map.end()가 되지는 않을 것이다.

만약 end()가 된다면 존재하지 않는 url이니까 해당하는 url을 기반으로 이미지를 생성해도 된다는 뜻이고

 

create함수에서 얘가 이미 있는 인스턴스인지 확인하는 부분이 if문이다. 

그리고 Image를 만들고 나서 , map에 정보를 추가해준다. 

 

main함수에서 img2 에서 image를 create 시도한다면

해당 url을 들고가서 map에서 확인을 해볼꺼고 이미 존재한 인스턴스임을 확인한 후에 

해당 인스턴스에 포인터값을 Return 해줘서 img1과 img2의 주소값을 동일할 것이다.

img1과 img2의 메모리 주소가 동일함을 확인할 수 있다.

 

그래서 Flyweight 기법은 동일한 instance가 무분별하게 재사용 되는 것을 막기 위해서 , 사용하는 기법이라고 이해할 수 있다.

'Programming > c++ Design Pattern' 카테고리의 다른 글

[C++] Iterator  (1) 2023.12.01
[C++ Design patter] Factory.  (1) 2023.11.30
[C++ Design Pattern] Adapter  (0) 2023.11.30
[C++ Design Pattern] Decorator  (0) 2023.11.29
[C++ Design Pattern] Composite  (1) 2023.11.29