Flyweight Pattern
Flyweight Pattern được sử dụng khi chúng ta cần tạo một số lượng lớn các đối tượng của 1 lớp nào đó. Do mỗi đối tượng đều đòi hỏi chiếm giữ một khoảng không gian bộ nhớ, nên với một số lượng lớn đối tượng được tạo ra có thể gây nên vấn đề nghiêm trọng đặc biệt đối với các thiết bị có dung lượng nhớ thấp. Flyweight Pattern có thể được áp dụng để giảm tải cho bộ nhớ thông qua cách chia sẻ các đối tượng.
Một số lưu ý khi áp dụng Flyweight Pattern:
- Số các đối tượng được ứng dụng tạo ra phải thực sự lớn.
- Việc tạo ra đối tượng đòi hỏi nhiều bộ nhớ và thời gian.
- Các thuộc tính của đối tượng có thể chia thành nhóm intrinsic và extrinsic. Trong đó, nhóm thuộc tính extrinsic của đối tượng nên được chương trình client xác lập.
Để áp dụng Flyweight Pattern, chúng ta cần xây dựng Flyweight Factory để trả về các đối tượng chia sẻ (dùng chung?). Như trong ví dụ sau, để tạo ra một bức hình gồm các đường thẳng và các hình oval thì chúng ta cần có một interface Shape và các implementation của nó là Line và Oval. Lớp Oval có các thuộc tính intrinsic để xác định xem thử có tô màu cho hình Oval hay không, trong khi lớp Line không có thuộc tính này.
1. Flyweight Design Pattern Interface and Concrete Classes
Shape.java
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); }
Line.javapackage 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.javapackage 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); } } }
2. Flyweight Factory
Flyweight Factory được chương trình client sử dụng để khởi tạo các đối tượng. Vì vậy chúng ta cần lưu giữ 1 ánh xạ các đối tượng trong factory - ánh xạ này không cho phép bên ngoài truy cập vào. Bất cứ khi nào chương trình client gọi khởi tạo đối tượng, nó sẽ được trả về từ cấu trúc HashMap. Chỉ khi không tìm được trong HashMap mới tạo ra đối tượng mới. Đối tượng mới được tạo ra cũng sẽ được đưa vào HashMap.
ShapeFactory.javapackage 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; } }
3. Flyweight Design Pattern Client Example
DrawingClient.javapackage 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); } }
Kết quả hiển thị

Màn hình console
Creating Line object Creating Oval object with fill=true Creating Oval object with fill=false
No comments :
Post a Comment