ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Composite
    Modeling/DesignPattern 2020. 2. 29. 19:09

    1. Overview

    Composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object.

    • We have a part-whole relationship or hierarchy of objects and we want to be able to treat all objects in this hierarchy uniformly.
    • This is not a simple composition concept from object-oriented programming but a further enhancement to that principal.
    • Think of composite pattern when dealing with tree structure of objects

    2. Description

    2.1 Implementation

    • Component must declare all methods that are applicable to both leaf and composite
    • We have to choose who defines the children management operations, component or composite
    • Then we implement the composite. An operation invoked on the composite is propagated to all its children
    • In leaf nodes, we have to handle the non-applicable operations like add/remove a child if they are defined in a component
    • In the end, composite pattern implementations will allow you to write algorithms without worrying about whether a node is a leaf or composite

    2.2 Consideration

    2.2.1 Implementation

    • You can provide a method to access parent of a node. This will simplify traversal of the entire tree
    • You can define the collection field to maintain children in a base component instead of composite but again that field has no use in leaf class.
    • In leaf objects can be repeated in the hierarchy then shared leaf nodes can be used to save memory and initialization costs. But again the number of nodes is a major deciding factor as using a cache for a small total number of nodes may cost more.

    2.2.2 Design

    • A decision needs to be made about where child management operations are defined. Defining them on components provides transparency but lead nodes are forced to implement those methods. Defining them on composite is safer but the client needs to be made aware of composite.
    • The overall goal of design should be to make the client code easier to implement when using composite. This is possible if the client code can work with a component interface only and doesn't need to worry about the leaf-composite distinction.

    2.3 Pitfalls

    • Difficult to restrict what is added to the hierarchy. If multiply types of leaf nodes are present in system then client code ends up doing runtime checks to ensure the operation is available on a node
    • Creating the original hierarchy can still be complex implementation especially if you are using caching to reuse nodes and the number of are quite high.

    3. Usage

    • UIViewRoot, UIOutput, and UIMessage in JSF

    4. Comparison with Decorator

    Composite Decorator
    Deals with tree structure of objects Simply contains anther (single) object
    Leaf nodes and composites have the same interface and composites simply delegate the operation to children Decorator add or modify the behavior of a contained object and do not have the notion of children

    5. Example

    //The component base class for composite pattern
    //defines operations applicable both leaf & composite
    abstract class File {
        private String name;
        public File(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public abstract void ls();
        // Child management operations
        public abstract void addFile(File file);
        public abstract File[] getFiles();
        public abstract boolean removeFile(File file);
    }
    //Composite in the composite pattern
    class Directory extends File{
        private List<File> children = new ArrayList<>();
        public Directory(String name) {
            super(name);
        }
        @Override
        public void ls() {
            System.out.println(getName());
            children.forEach(File::ls);
        }
        @Override
        public void addFile(File file) {
            children.add(file);
        }
        @Override
        public File[] getFiles() {
            return children.toArray(new File[children.size()]);
        }
        @Override
        public boolean removeFile(File file) {
            return children.remove(file);
        }
    }
    //Leaf node in composite pattern
    class BinaryFile extends File {
    
        private long size;
    
        public BinaryFile(String name, long size) {
            super(name);
            this.size = size;
        }
        @Override
        public void ls() {
            System.out.println(getName() + "\t" + size);
        }
        @Override
        public void addFile(File file) {
            throw new UnsupportedOperationException("Leaf node doesn't support add operation");
        }
        @Override
        public File[] getFiles() {
            throw new UnsupportedOperationException("Leaf node doesn't support add operation");
        }
        @Override
        public boolean removeFile(File file) {
            throw new UnsupportedOperationException("Leaf node doesn't support add operation");
        }
    }
    public class Client {
        public static void main(String[] args) {
            File root1 = createTreeOne();
            root1.ls();
            System.out.println("**************");
            File root2 = createTreeTwo();
            root2.ls();
        }
    //    Client builds tree using leaf and composites
    	private static File createTreeOne() {
    		File file1 = new BinaryFile("File1", 1000);
    		Directory dir1 = new Directory("dir1");
    		dir1.addFile(file1);
    		File file2 = new BinaryFile("file2", 2000);
    		File file3 = new BinaryFile("file3", 150);
    		Directory dir2 = new Directory("dir2");
    		dir2.addFile(file2);
    		dir2.addFile(file3);
    		dir2.addFile(dir1);
    		return dir2;
    	}
    
    	private static File createTreeTwo() {
    		return new BinaryFile("Another file", 200);
    	}
    }

    6. Reference

    https://en.wikipedia.org/wiki/Composite_pattern

    https://courseprobe.com/instructors/coffee-powered-crew/

    'Modeling > DesignPattern' 카테고리의 다른 글

    Mediator  (0) 2020.03.01
    Memento  (0) 2020.03.01
    Chain of responsibility  (0) 2020.02.29
    Visitor  (0) 2020.02.29
    Iterator  (0) 2020.02.29

    댓글

Designed by Tistory.