웹사이트 검색

Java의 Flyweight 디자인 패턴


오늘은 플라이웨이트 디자인 패턴에 대해 알아보겠습니다.

플라이급 디자인 패턴

GoF에 따르면 플라이웨이트 디자인 패턴 의도는 다음과 같습니다.

공유를 사용하여 많은 수의 세분화된 개체를 효율적으로 지원

Flyweight 디자인 패턴은 Decorator 패턴과 같은 Structural 디자인 패턴입니다. Flyweight 디자인 패턴은 클래스의 객체를 많이 생성해야 할 때 사용됩니다. 모든 개체는 모바일 장치나 임베디드 시스템과 같은 메모리가 적은 장치에 중요할 수 있는 메모리 공간을 소비하므로 플라이웨이트 디자인 패턴을 적용하여 개체를 공유하여 메모리 부하를 줄일 수 있습니다. 플라이웨이트 디자인 패턴을 적용하기 전에 다음 요소를 고려해야 합니다.

  • 응용 프로그램에서 생성할 개체의 수가 엄청날 것입니다.
  • 개체 생성은 메모리 사용량이 많고 시간도 많이 소요될 수 있습니다.
  • 개체 속성은 내재적 속성과 외재적 속성으로 나눌 수 있으며 개체의 외재적 속성은 클라이언트 프로그램에서 정의해야 합니다.

플라이웨이트 패턴을 적용하려면 Object 속성을 고유 속성과 외부 속성으로 구분해야 합니다. 고유 속성은 개체를 고유하게 만드는 반면 외부 속성은 클라이언트 코드에 의해 설정되고 다른 작업을 수행하는 데 사용됩니다. 예를 들어 개체 원은 색상 및 너비와 같은 외부 속성을 가질 수 있습니다. 플라이웨이트 패턴을 적용하기 위해서는 공유 객체를 반환하는 플라이웨이트 팩토리를 생성해야 합니다. 예를 들어 선과 타원으로 그림을 만들어야 한다고 가정해 보겠습니다. 따라서 Shape 인터페이스와 LineOval과 같은 구체적인 구현을 갖게 됩니다. Oval 클래스는 주어진 색상으로 Oval을 채울지 여부를 결정하는 고유 속성을 갖지만 Line에는 고유 속성이 없습니다.

플라이웨이트 설계 패턴 인터페이스 및 구체적인 클래스

모양.자바

package com.journaldev.design.flyweight;

import java.awt.Color;
import java.awt.Graphics;

public interface Shape {

	public void draw(Graphics g, int x, int y, int width, int height,
			Color color);
}

라인.자바

package com.journaldev.design.flyweight;

import java.awt.Color;
import java.awt.Graphics;

public class Line implements Shape {

	public Line(){
		System.out.println("Creating Line object");
		//adding time delay
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void draw(Graphics line, int x1, int y1, int x2, int y2,
			Color color) {
		line.setColor(color);
		line.drawLine(x1, y1, x2, y2);
	}

}

Oval.java

package com.journaldev.design.flyweight;

import java.awt.Color;
import java.awt.Graphics;

public class Oval implements Shape {
	
	//intrinsic property
	private boolean fill;
	
	public Oval(boolean f){
		this.fill=f;
		System.out.println("Creating Oval object with fill="+f);
		//adding time delay
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void draw(Graphics circle, int x, int y, int width, int height,
			Color color) {
		circle.setColor(color);
		circle.drawOval(x, y, width, height);
		if(fill){
			circle.fillOval(x, y, width, height);
		}
	}

}

인스턴스화하는 동안 많은 시간이 걸리는 객체에 플라이웨이트 패턴을 사용할 수 있다는 점을 강조하기 위해 구체적인 클래스의 객체를 생성할 때 의도적으로 지연을 도입했습니다.

플라이급 공장

플라이웨이트 팩터리는 클라이언트 프로그램에서 개체를 인스턴스화하는 데 사용되므로 클라이언트 응용 프로그램에서 액세스할 수 없는 개체 맵을 팩터리에 유지해야 합니다. 클라이언트 프로그램이 Object의 인스턴스를 가져오기 위해 호출할 때마다 HashMap에서 반환되어야 하며, 찾지 못하면 새 Object를 만들어 Map에 넣은 다음 반환해야 합니다. 객체를 생성하는 동안 모든 고유 속성이 고려되었는지 확인해야 합니다. 플라이웨이트 팩토리 클래스는 아래 코드와 같습니다. ShapeFactory.java

package com.journaldev.design.flyweight;

import java.util.HashMap;

public class ShapeFactory {

	private static final HashMap<ShapeType,Shape> shapes = new HashMap<ShapeType,Shape>();

	public static Shape getShape(ShapeType type) {
		Shape shapeImpl = shapes.get(type);

		if (shapeImpl == null) {
			if (type.equals(ShapeType.OVAL_FILL)) {
				shapeImpl = new Oval(true);
			} else if (type.equals(ShapeType.OVAL_NOFILL)) {
				shapeImpl = new Oval(false);
			} else if (type.equals(ShapeType.LINE)) {
				shapeImpl = new Line();
			}
			shapes.put(type, shapeImpl);
		}
		return shapeImpl;
	}
	
	public static enum ShapeType{
		OVAL_FILL,OVAL_NOFILL,LINE;
	}
}

getShape 메서드에서 Factory 패턴을 사용하는 것에 주목하세요.

Flyweight 디자인 패턴 클라이언트 예제

다음은 플라이웨이트 패턴 구현을 사용하는 샘플 프로그램입니다. DrawingClient.java

package com.journaldev.design.flyweight;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.journaldev.design.flyweight.ShapeFactory.ShapeType;

public class DrawingClient extends JFrame{

	private static final long serialVersionUID = -1350200437285282550L;
	private final int WIDTH;
	private final int HEIGHT;

	private static final ShapeType shapes[] = { ShapeType.LINE, ShapeType.OVAL_FILL,ShapeType.OVAL_NOFILL };
	private static final Color colors[] = { Color.RED, Color.GREEN, Color.YELLOW };
	
	public DrawingClient(int width, int height){
		this.WIDTH=width;
		this.HEIGHT=height;
		Container contentPane = getContentPane();

		JButton startButton = new JButton("Draw");
		final JPanel panel = new JPanel();

		contentPane.add(panel, BorderLayout.CENTER);
		contentPane.add(startButton, BorderLayout.SOUTH);
		setSize(WIDTH, HEIGHT);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);

		startButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				Graphics g = panel.getGraphics();
				for (int i = 0; i < 20; ++i) {
					Shape shape = ShapeFactory.getShape(getRandomShape());
					shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),
							getRandomHeight(), getRandomColor());
				}
			}
		});
	}
	
	private ShapeType getRandomShape() {
		return shapes[(int) (Math.random() * shapes.length)];
	}

	private int getRandomX() {
		return (int) (Math.random() * WIDTH);
	}

	private int getRandomY() {
		return (int) (Math.random() * HEIGHT);
	}

	private int getRandomWidth() {
		return (int) (Math.random() * (WIDTH / 10));
	}

	private int getRandomHeight() {
		return (int) (Math.random() * (HEIGHT / 10));
	}

	private Color getRandomColor() {
		return colors[(int) (Math.random() * colors.length)];
	}

	public static void main(String[] args) {
		DrawingClient drawing = new DrawingClient(500,600);
	}
}
Creating Line object
Creating Oval object with fill=true
Creating Oval object with fill=false

플라이웨이트 패턴은 여기까지입니다. 향후 게시물에서 더 많은 디자인 패턴을 살펴보겠습니다. 마음에 드셨다면 댓글 섹션에서 의견을 공유하고 다른 사람들과도 공유하세요.

JDK의 플라이웨이트 디자인 패턴 예제

모든 문자열 풀 구현.

플라이웨이트 디자인 패턴 중요 포인트

  1. 이 예제에서 클라이언트 코드는 Flyweight 팩터리를 사용하여 객체를 생성하도록 강제하지 않지만 클라이언트 코드가 플라이웨이트 패턴 구현을 사용하지만 특정 애플리케이션에 대한 완전한 디자인 결정을 사용하도록 강제할 수 있습니다.
  2. 플라이웨이트 패턴은 복잡성을 가져오고 공유 개체 수가 크면 메모리와 시간 사이에 트레이드가 있으므로 요구 사항에 따라 신중하게 사용해야 합니다.
  3. Flyweight 패턴 구현은 Object의 고유 속성 수가 너무 많아 Factory 클래스 구현이 복잡할 때 유용하지 않습니다.

이것이 Java의 Flyweight 디자인 패턴의 전부입니다.