Composite Design Pattern
Obyektləri ağac strukturunda təşkil etməyə imkan verir. Bu pattern, tək obyektləri və obyektlərin kompozisiyalarını eyni şəkildə işləməyə imkan verir.
Composite pattern, real həyatda fayl sisteminə bənzəyir. Həm fayllar, həm də qovluqlar eyni əməliyyatlara tab tutur (kopyalama, silinmə, adının dəyişdirilməsi), lakin qovluqlar içərisində başqa fayllar və qovluqlar saxlaya bilir.
Composite Pattern-nin Əsas Xüsusiyyətləri
- Tree Structure: Ağac strukturunda obyektləri təşkil edir
- Uniform Treatment: Tək obyektlər və kompozisiyalar eyni cür işlənir
- Recursive Composition: Kompozisiyalar digər kompozisiyaları ehtiva edə bilər
- Client Simplicity: Client tək obyekt və kompozisiya arasında fərq görmür
Composite Pattern-nin Strukturu
- Component: Tək obyektlər və kompozisiyalar üçün ümumi interface
- Leaf: Ağacın yarpaq düyümləri, başqa obyektləri ehtiva etmir
- Composite: Digər komponentləri ehtiva edən konteyner obyekti
- Client: Component interface-i istifadə edən class
Java-da Composite Pattern İmplementasiyası
File System Nümunəsi
Koda bax
// Component interface
interface FileSystemComponent {
void showDetails();
long getSize();
String getName();
}
// Leaf class - File
class File implements FileSystemComponent {
private String name;
private long size;
public File(String name, long size) {
this.name = name;
this.size = size;
}
@Override
public void showDetails() {
System.out.println("File: " + name + " (" + size + " bytes)");
}
@Override
public long getSize() {
return size;
}
@Override
public String getName() {
return name;
}
}
// Composite class - Directory
class Directory implements FileSystemComponent {
private String name;
private java.util.List<FileSystemComponent> components = new java.util.ArrayList<>();
public Directory(String name) {
this.name = name;
}
public void addComponent(FileSystemComponent component) {
components.add(component);
System.out.println(component.getName() + " added to " + name);
}
public void removeComponent(FileSystemComponent component) {
components.remove(component);
System.out.println(component.getName() + " removed from " + name);
}
@Override
public void showDetails() {
System.out.println("Directory: " + name + " (" + getSize() + " bytes total)");
for (FileSystemComponent component : components) {
System.out.print(" ");
component.showDetails();
}
}
@Override
public long getSize() {
long totalSize = 0;
for (FileSystemComponent component : components) {
totalSize += component.getSize();
}
return totalSize;
}
@Override
public String getName() {
return name;
}
public java.util.List<FileSystemComponent> getComponents() {
return components;
}
}
// Client code
public class CompositePatternDemo {
public static void main(String[] args) {
// Create files
File file1 = new File("document.txt", 1024);
File file2 = new File("image.jpg", 2048);
File file3 = new File("music.mp3", 5120);
File file4 = new File("video.mp4", 10240);
// Create directories
Directory rootDir = new Directory("Root");
Directory documentsDir = new Directory("Documents");
Directory mediaDir = new Directory("Media");
Directory imagesDir = new Directory("Images");
// Build directory structure
System.out.println("Building directory structure...");
rootDir.addComponent(documentsDir);
rootDir.addComponent(mediaDir);
documentsDir.addComponent(file1);
mediaDir.addComponent(imagesDir);
mediaDir.addComponent(file3);
mediaDir.addComponent(file4);
imagesDir.addComponent(file2);
System.out.println("\nDirectory structure:");
rootDir.showDetails();
System.out.println("\nTotal size of root directory: " + rootDir.getSize() + " bytes");
}
}
Çıxış:
Building directory structure...
Documents added to Root
Media added to Root
document.txt added to Documents
Images added to Media
music.mp3 added to Media
video.mp4 added to Media
image.jpg added to Images
Directory structure:
Directory: Root (18432 bytes total)
Directory: Documents (1024 bytes total)
File: document.txt (1024 bytes)
Directory: Media (17408 bytes total)
Directory: Images (2048 bytes total)
File: image.jpg (2048 bytes)
File: music.mp3 (5120 bytes)
File: video.mp4 (10240 bytes)
Total size of root directory: 18432 bytes
Graphic Elements Nümunəsi
Koda bax
// Component interface for graphics
interface Graphic {
void draw();
void move(int x, int y);
int getArea();
}
// Leaf class - Circle
class Circle implements Graphic {
private int x, y, radius;
public Circle(int x, int y, int radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
System.out.println("Drawing Circle at (" + x + ", " + y + ") with radius " + radius);
}
@Override
public void move(int deltaX, int deltaY) {
this.x += deltaX;
this.y += deltaY;
System.out.println("Circle moved to (" + x + ", " + y + ")");
}
@Override
public int getArea() {
return (int) (Math.PI * radius * radius);
}
}
// Leaf class - Rectangle
class Rectangle implements Graphic {
private int x, y, width, height;
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
@Override
public void draw() {
System.out.println("Drawing Rectangle at (" + x + ", " + y + ") with size " + width + "x" + height);
}
@Override
public void move(int deltaX, int deltaY) {
this.x += deltaX;
this.y += deltaY;
System.out.println("Rectangle moved to (" + x + ", " + y + ")");
}
@Override
public int getArea() {
return width * height;
}
}
// Composite class - Group
class GraphicGroup implements Graphic {
private String name;
private java.util.List<Graphic> graphics = new java.util.ArrayList<>();
public GraphicGroup(String name) {
this.name = name;
}
public void add(Graphic graphic) {
graphics.add(graphic);
System.out.println("Graphic added to group: " + name);
}
public void remove(Graphic graphic) {
graphics.remove(graphic);
System.out.println("Graphic removed from group: " + name);
}
@Override
public void draw() {
System.out.println("Drawing group: " + name);
for (Graphic graphic : graphics) {
graphic.draw();
}
}
@Override
public void move(int deltaX, int deltaY) {
System.out.println("Moving group: " + name);
for (Graphic graphic : graphics) {
graphic.move(deltaX, deltaY);
}
}
@Override
public int getArea() {
int totalArea = 0;
for (Graphic graphic : graphics) {
totalArea += graphic.getArea();
}
return totalArea;
}
}
// Client code for graphics demo
public class GraphicsCompositeDemo {
public static void main(String[] args) {
// Create individual graphics
Circle circle1 = new Circle(10, 20, 5);
Circle circle2 = new Circle(30, 40, 8);
Rectangle rect1 = new Rectangle(0, 0, 20, 15);
Rectangle rect2 = new Rectangle(50, 60, 25, 10);
// Create groups
GraphicGroup shapeGroup = new GraphicGroup("Shapes");
GraphicGroup allGraphics = new GraphicGroup("All Graphics");
// Build composite structure
System.out.println("Building composite structure...");
shapeGroup.add(circle1);
shapeGroup.add(rect1);
allGraphics.add(shapeGroup);
allGraphics.add(circle2);
allGraphics.add(rect2);
System.out.println("\nDrawing all graphics:");
allGraphics.draw();
System.out.println("\nTotal area: " + allGraphics.getArea());
System.out.println("\nMoving all graphics by (10, 10):");
allGraphics.move(10, 10);
}
}
Composite Pattern-nin Üstünlükləri
- Flexibility: Ağac strukturu dinamik şəkildə dəyişdirilə bilər
- Uniform Interface: Tək obyektlər və kompozisiyalar eyni interface istifadə edir
- Recursive Operations: Əməliyyatlar avtomatik olaraq bütün strukturda tətbiq edilir
- Easy Extension: Yeni komponent növləri asanlıqla əlavə edilə bilər
Composite Pattern-nin Çatışmazlıqları
- Type Safety: Bütün komponentlər eyni interface-ə malik olmalıdır
- Complexity: Sadə strukturlar üçün həddən artıq mürəkkəb ola bilər
- Performance: Böyük ağac strukturlarında performans problemi yarana bilər
İstifadə Halları
- GUI Components: UI elementlərinin ierarxik strukturu
- File Systems: Fayl və qovluq strukturu
- Organization Charts: Təşkilat strukturunun təsviri
- Mathematical Expressions: Mürəkkəb hesablama ifadələri
- Game Development: Oyun obyektlərinin ierarxiyası
Composite vs Decorator Pattern
- Composite: Obyektlərin ağac strukturunda təşkili
- Decorator: Obyektlərin zəncir şəklində genişləndirilməsi
Composite Pattern, ierarxik strukturları təşkil etmək üçün çox faydalı bir pattern-dir və xüsusilə ağac məlumat strukturları tələb olunan aplikasiyalarda geniş istifadə olunur.