#Design_Patterns
#Structural_patterns
#Composite_Design_Pattern
👉Intent
▪️Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
▪️Recursive composition
▪️"Directories contain entries, each of which could be a directory."
▪️1-to-many "has a" up the "is a" hierarchy
@javaCode☕️
#Structural_patterns
#Composite_Design_Pattern
👉Intent
▪️Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
▪️Recursive composition
▪️"Directories contain entries, each of which could be a directory."
▪️1-to-many "has a" up the "is a" hierarchy
@javaCode☕️
#Composite_Design_Pattern
👉Problem
Application needs to manipulate a hierarchical collection of "primitive" and "composite" objects. Processing of a primitive object is handled one way, and processing of a composite object is handled differently. Having to query the "type" of each object before attempting to process it is not desirable.
@javaCode☕️
👉Problem
Application needs to manipulate a hierarchical collection of "primitive" and "composite" objects. Processing of a primitive object is handled one way, and processing of a composite object is handled differently. Having to query the "type" of each object before attempting to process it is not desirable.
@javaCode☕️
#Composite_Design_Pattern
👉Discussion
Define an abstract base class (Component) that specifies the behavior that needs to be exercised uniformly across all primitive and composite objects. Subclass the Primitive and Composite classes off of the Component class. Each Composite object "couples" itself only to the abstract type Component as it manages its "children".
Use this pattern whenever you have "composites that contain components, each of which could be a composite".
Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Primitives and Composites uniformly requires that these methods be moved to the abstract Component class. See the "Opinions" section below for a discussion of "safety" versus "transparency" issues.
@javaCode☕️
👉Discussion
Define an abstract base class (Component) that specifies the behavior that needs to be exercised uniformly across all primitive and composite objects. Subclass the Primitive and Composite classes off of the Component class. Each Composite object "couples" itself only to the abstract type Component as it manages its "children".
Use this pattern whenever you have "composites that contain components, each of which could be a composite".
Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Primitives and Composites uniformly requires that these methods be moved to the abstract Component class. See the "Opinions" section below for a discussion of "safety" versus "transparency" issues.
@javaCode☕️
👍1
☕️JAVA Language Community
#Composite_Design_Pattern @javaCode☕️
👉Structure
Composites that contain Components, each of which could be a Composite.
Menus that contain menu items, each of which could be a menu.
Row-column GUI layout managers that contain widgets, each of which could be a row-column GUI layout manager.
Directories that contain files, each of which could be a directory.
Containers that contain Elements, each of which could be a Container.
#Composite_Design_Pattern
@javaCode☕️
Composites that contain Components, each of which could be a Composite.
Menus that contain menu items, each of which could be a menu.
Row-column GUI layout managers that contain widgets, each of which could be a row-column GUI layout manager.
Directories that contain files, each of which could be a directory.
Containers that contain Elements, each of which could be a Container.
#Composite_Design_Pattern
@javaCode☕️
👍1
#Composite_Design_Pattern
👉Example
The Composite composes objects into tree structures and lets clients treat individual objects and compositions uniformly. Although the example is abstract, arithmetic expressions are Composites. An arithmetic expression consists of an operand, an operator (+ - * /), and another operand. The operand can be a number, or another arithmetic expression. Thus, 2 + 3 and (2 + 3) + (4 * 6) are both valid expressions.
@javaCode☕️
👉Example
The Composite composes objects into tree structures and lets clients treat individual objects and compositions uniformly. Although the example is abstract, arithmetic expressions are Composites. An arithmetic expression consists of an operand, an operator (+ - * /), and another operand. The operand can be a number, or another arithmetic expression. Thus, 2 + 3 and (2 + 3) + (4 * 6) are both valid expressions.
@javaCode☕️
#Composite_Design_Pattern
👉Check list
1️⃣Ensure that your problem is about representing "whole-part" hierarchical relationships.
2️⃣Consider the heuristic, "Containers that contain containees, each of which could be a container." For example, "Assemblies that contain components, each of which could be an assembly." Divide your domain concepts into container classes, and containee classes.
3️⃣Create a "lowest common denominator" interface that makes your containers and containees interchangeable. It should specify the behavior that needs to be exercised uniformly across all containee and container objects.
4️⃣All container and containee classes declare an "is a" relationship to the interface.
5️⃣All container classes declare a one-to-many "has a" relationship to the interface.
6️⃣Container classes leverage polymorphism to delegate to their containee objects.
7️⃣Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Leaf and Composite objects uniformly may require that these methods be promoted to the abstract Component class. See the Gang of Four for a discussion of these "safety" versus "transparency" trade-offs.
@javaCode☕️
👉Check list
1️⃣Ensure that your problem is about representing "whole-part" hierarchical relationships.
2️⃣Consider the heuristic, "Containers that contain containees, each of which could be a container." For example, "Assemblies that contain components, each of which could be an assembly." Divide your domain concepts into container classes, and containee classes.
3️⃣Create a "lowest common denominator" interface that makes your containers and containees interchangeable. It should specify the behavior that needs to be exercised uniformly across all containee and container objects.
4️⃣All container and containee classes declare an "is a" relationship to the interface.
5️⃣All container classes declare a one-to-many "has a" relationship to the interface.
6️⃣Container classes leverage polymorphism to delegate to their containee objects.
7️⃣Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Leaf and Composite objects uniformly may require that these methods be promoted to the abstract Component class. See the Gang of Four for a discussion of these "safety" versus "transparency" trade-offs.
@javaCode☕️
#Composite_Design_Pattern
👉Rules of thumb
1️⃣Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
2️⃣Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.
3️⃣Composite can let you compose a Mediator out of smaller pieces through recursive composition.
4️⃣Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.
5️⃣Flyweight is often combined with Composite to implement shared leaf nodes.
@javaCode☕️
👉Rules of thumb
1️⃣Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
2️⃣Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.
3️⃣Composite can let you compose a Mediator out of smaller pieces through recursive composition.
4️⃣Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.
5️⃣Flyweight is often combined with Composite to implement shared leaf nodes.
@javaCode☕️
👍1
#Composite_Design_Pattern
👉Opinions
The whole point of the Composite pattern is that the Composite can be treated atomically, just like a leaf. If you want to provide an Iterator protocol, fine, but I think that is outside the pattern itself. At the heart of this pattern is the ability for a client to perform operations on an object without needing to know that there are many objects inside.
☑️to be continued...
@javaCode☕️
👉Opinions
The whole point of the Composite pattern is that the Composite can be treated atomically, just like a leaf. If you want to provide an Iterator protocol, fine, but I think that is outside the pattern itself. At the heart of this pattern is the ability for a client to perform operations on an object without needing to know that there are many objects inside.
☑️to be continued...
@javaCode☕️
☕️JAVA Language Community
👉Opinion Being able to treat a heterogeneous collection of objects atomically (or transparently) requires that the "child management" interface be defined at the root of the Composite class hierarchy (the abstract Component class). However, this choice costs…
#Composite_Design_Pattern
👉Opinion
My Component classes do not know that Composites exist. They provide no help for navigating Composites, nor any help for altering the contents of a Composite. This is because I would like the base class (and all its derivatives) to be reusable in contexts that do not require Composites. When given a base class pointer, if I absolutely need to know whether or not it is a Composite, I will use dynamic_cast to figure this out. In those cases where dynamic_cast is too expensive, I will use a Visitor.
Common complaint: "if I push the Composite interface down into the Composite class, how am I going to enumerate (i.e. traverse) a complex structure?" My answer is that when I have behaviors which apply to hierarchies like the one presented in the Composite pattern, I typically use Visitor, so enumeration isn't a problem - the Visitor knows in each case, exactly what kind of object it's dealing with. The Visitor doesn't need every object to provide an enumeration interface.
☑️to be continued...
@javaCode☕️
👉Opinion
My Component classes do not know that Composites exist. They provide no help for navigating Composites, nor any help for altering the contents of a Composite. This is because I would like the base class (and all its derivatives) to be reusable in contexts that do not require Composites. When given a base class pointer, if I absolutely need to know whether or not it is a Composite, I will use dynamic_cast to figure this out. In those cases where dynamic_cast is too expensive, I will use a Visitor.
Common complaint: "if I push the Composite interface down into the Composite class, how am I going to enumerate (i.e. traverse) a complex structure?" My answer is that when I have behaviors which apply to hierarchies like the one presented in the Composite pattern, I typically use Visitor, so enumeration isn't a problem - the Visitor knows in each case, exactly what kind of object it's dealing with. The Visitor doesn't need every object to provide an enumeration interface.
☑️to be continued...
@javaCode☕️