mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-14 22:17:38 +00:00
docs: update composite view
This commit is contained in:
1 parent
fd109955dc
commit
d3e7401f70
1 file changed
+249
-185
+249
-185
@@ -3,32 +3,35 @@ title: Composite View
|
|||||||
category: Structural
|
category: Structural
|
||||||
language: en
|
language: en
|
||||||
tag:
|
tag:
|
||||||
- Enterprise patterns
|
- Enterprise patterns
|
||||||
- Presentation
|
- Presentation
|
||||||
---
|
---
|
||||||
|
|
||||||
## Name
|
|
||||||
**Composite View**
|
|
||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
The purpose of the Composite View Pattern is to increase re-usability and flexibility when creating views for websites/webapps.
|
|
||||||
This pattern seeks to decouple the content of the page from its layout, allowing changes to be made to either the content
|
The primary goal of the Composite View design pattern is to compose objects into tree structures to represent part-whole
|
||||||
or layout of the page without impacting the other. This pattern also allows content to be easily reused across different views easily.
|
hierarchies. This allows clients to treat individual objects and compositions of objects uniformly, simplifying the
|
||||||
|
management of complex structures.
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real World Example
|
Real World Example
|
||||||
|
|
||||||
> A news site wants to display the current date and news to different users
|
> A news site wants to display the current date and news to different users
|
||||||
> based on that user's preferences. The news site will substitute in different news feed
|
> based on that user's preferences. The news site will substitute in different news feed
|
||||||
> components depending on the user's interest, defaulting to local news.
|
> components depending on the user's interest, defaulting to local news.
|
||||||
|
|
||||||
In Plain Words
|
In Plain Words
|
||||||
|
|
||||||
> Composite View Pattern is having a main view being composed of smaller subviews.
|
> Composite View Pattern is having a main view being composed of smaller subviews.
|
||||||
> The layout of this composite view is based on a template. A View-manager then decides which
|
> The layout of this composite view is based on a template. A View-manager then decides which
|
||||||
> subviews to include in this template.
|
> subviews to include in this template.
|
||||||
|
|
||||||
Wikipedia Says
|
Wikipedia Says
|
||||||
|
|
||||||
> Composite views that are composed of multiple atomic subviews. Each component of
|
> Composite views that are composed of multiple atomic subviews. Each component of
|
||||||
> the template may be included dynamically into the whole and the layout of the page may be managed independently of the content.
|
> the template may be included dynamically into the whole and the layout of the page may be managed independently of the
|
||||||
|
> content.
|
||||||
> This solution provides for the creation of a composite view based on the inclusion and substitution of
|
> This solution provides for the creation of a composite view based on the inclusion and substitution of
|
||||||
> modular dynamic and static template fragments.
|
> modular dynamic and static template fragments.
|
||||||
> It promotes the reuse of atomic portions of the view by encouraging modular design.
|
> It promotes the reuse of atomic portions of the view by encouraging modular design.
|
||||||
@@ -39,162 +42,187 @@ Since this is a web development pattern, a server is required to demonstrate it.
|
|||||||
This example uses Tomcat 10.0.13 to run the servlet, and this programmatic example will only work with Tomcat 10+.
|
This example uses Tomcat 10.0.13 to run the servlet, and this programmatic example will only work with Tomcat 10+.
|
||||||
|
|
||||||
Firstly there is `AppServlet` which is an `HttpServlet` that runs on Tomcat 10+.
|
Firstly there is `AppServlet` which is an `HttpServlet` that runs on Tomcat 10+.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class AppServlet extends HttpServlet {
|
public class AppServlet extends HttpServlet {
|
||||||
private String msgPartOne = "<h1>This Server Doesn't Support";
|
private String msgPartOne = "<h1>This Server Doesn't Support";
|
||||||
private String msgPartTwo = "Requests</h1>\n"
|
private String msgPartTwo = "Requests</h1>\n"
|
||||||
+ "<h2>Use a GET request with boolean values for the following parameters<h2>\n"
|
+ "<h2>Use a GET request with boolean values for the following parameters<h2>\n"
|
||||||
+ "<h3>'name'</h3>\n<h3>'bus'</h3>\n<h3>'sports'</h3>\n<h3>'sci'</h3>\n<h3>'world'</h3>";
|
+ "<h3>'name'</h3>\n<h3>'bus'</h3>\n<h3>'sports'</h3>\n<h3>'sci'</h3>\n<h3>'world'</h3>";
|
||||||
|
|
||||||
private String destination = "newsDisplay.jsp";
|
private String destination = "newsDisplay.jsp";
|
||||||
|
|
||||||
public AppServlet() {
|
public AppServlet() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doGet(HttpServletRequest req, HttpServletResponse resp)
|
public void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);
|
RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);
|
||||||
ClientPropertiesBean reqParams = new ClientPropertiesBean(req);
|
ClientPropertiesBean reqParams = new ClientPropertiesBean(req);
|
||||||
req.setAttribute("properties", reqParams);
|
req.setAttribute("properties", reqParams);
|
||||||
requestDispatcher.forward(req, resp);
|
requestDispatcher.forward(req, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPost(HttpServletRequest req, HttpServletResponse resp)
|
public void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
resp.setContentType("text/html");
|
resp.setContentType("text/html");
|
||||||
PrintWriter out = resp.getWriter();
|
PrintWriter out = resp.getWriter();
|
||||||
out.println(msgPartOne + " Post " + msgPartTwo);
|
out.println(msgPartOne + " Post " + msgPartTwo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doDelete(HttpServletRequest req, HttpServletResponse resp)
|
public void doDelete(HttpServletRequest req, HttpServletResponse resp)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
resp.setContentType("text/html");
|
resp.setContentType("text/html");
|
||||||
PrintWriter out = resp.getWriter();
|
PrintWriter out = resp.getWriter();
|
||||||
out.println(msgPartOne + " Delete " + msgPartTwo);
|
out.println(msgPartOne + " Delete " + msgPartTwo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPut(HttpServletRequest req, HttpServletResponse resp)
|
public void doPut(HttpServletRequest req, HttpServletResponse resp)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
resp.setContentType("text/html");
|
resp.setContentType("text/html");
|
||||||
PrintWriter out = resp.getWriter();
|
PrintWriter out = resp.getWriter();
|
||||||
out.println(msgPartOne + " Put " + msgPartTwo);
|
out.println(msgPartOne + " Put " + msgPartTwo);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This servlet is not part of the pattern, and simply forwards GET requests to the correct JSP.
|
This servlet is not part of the pattern, and simply forwards GET requests to the correct JSP.
|
||||||
PUT, POST, and DELETE requests are not supported and will simply show an error message.
|
PUT, POST, and DELETE requests are not supported and will simply show an error message.
|
||||||
|
|
||||||
The view management in this example is done via a javabean class: `ClientPropertiesBean`, which stores user preferences.
|
The view management in this example is done via a javabean class: `ClientPropertiesBean`, which stores user preferences.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class ClientPropertiesBean implements Serializable {
|
public class ClientPropertiesBean implements Serializable {
|
||||||
|
|
||||||
private static final String WORLD_PARAM = "world";
|
private static final String WORLD_PARAM = "world";
|
||||||
private static final String SCIENCE_PARAM = "sci";
|
private static final String SCIENCE_PARAM = "sci";
|
||||||
private static final String SPORTS_PARAM = "sport";
|
private static final String SPORTS_PARAM = "sport";
|
||||||
private static final String BUSINESS_PARAM = "bus";
|
private static final String BUSINESS_PARAM = "bus";
|
||||||
private static final String NAME_PARAM = "name";
|
private static final String NAME_PARAM = "name";
|
||||||
|
|
||||||
private static final String DEFAULT_NAME = "DEFAULT_NAME";
|
private static final String DEFAULT_NAME = "DEFAULT_NAME";
|
||||||
private boolean worldNewsInterest;
|
private boolean worldNewsInterest;
|
||||||
private boolean sportsInterest;
|
private boolean sportsInterest;
|
||||||
private boolean businessInterest;
|
private boolean businessInterest;
|
||||||
private boolean scienceNewsInterest;
|
private boolean scienceNewsInterest;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
public ClientPropertiesBean() {
|
public ClientPropertiesBean() {
|
||||||
worldNewsInterest = true;
|
worldNewsInterest = true;
|
||||||
sportsInterest = true;
|
sportsInterest = true;
|
||||||
businessInterest = true;
|
businessInterest = true;
|
||||||
scienceNewsInterest = true;
|
scienceNewsInterest = true;
|
||||||
name = DEFAULT_NAME;
|
name = DEFAULT_NAME;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientPropertiesBean(HttpServletRequest req) {
|
|
||||||
worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));
|
|
||||||
sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));
|
|
||||||
businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));
|
|
||||||
scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));
|
|
||||||
String tempName = req.getParameter(NAME_PARAM);
|
|
||||||
if (tempName == null || tempName == "") {
|
|
||||||
tempName = DEFAULT_NAME;
|
|
||||||
}
|
}
|
||||||
name = tempName;
|
|
||||||
}
|
public ClientPropertiesBean(HttpServletRequest req) {
|
||||||
// getters and setters generated by Lombok
|
worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));
|
||||||
|
sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));
|
||||||
|
businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));
|
||||||
|
scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));
|
||||||
|
String tempName = req.getParameter(NAME_PARAM);
|
||||||
|
if (tempName == null || tempName == "") {
|
||||||
|
tempName = DEFAULT_NAME;
|
||||||
|
}
|
||||||
|
name = tempName;
|
||||||
|
}
|
||||||
|
// getters and setters generated by Lombok
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This javabean has a default constructor, and another that takes an `HttpServletRequest`.
|
This javabean has a default constructor, and another that takes an `HttpServletRequest`.
|
||||||
This second constructor takes the request object, parses out the request parameters which contain the
|
This second constructor takes the request object, parses out the request parameters which contain the
|
||||||
user preferences for different types of news.
|
user preferences for different types of news.
|
||||||
|
|
||||||
The template for the news page is in `newsDisplay.jsp`
|
The template for the news page is in `newsDisplay.jsp`
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
h1 { text-align: center;}
|
h1 {
|
||||||
h2 { text-align: center;}
|
text-align: center;
|
||||||
h3 { text-align: center;}
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.centerTable {
|
.centerTable {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
table {border: 1px solid black;}
|
|
||||||
tr {text-align: center;}
|
table {
|
||||||
td {text-align: center;}
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute("properties");%>
|
<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute("properties");%>
|
||||||
<h1>Welcome <%= propertiesBean.getName()%></h1>
|
<h1>Welcome <%= propertiesBean.getName()%></h1>
|
||||||
<jsp:include page="header.jsp"></jsp:include>
|
<jsp:include page="header.jsp"></jsp:include>
|
||||||
<table class="centerTable">
|
<table class="centerTable">
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<% if(propertiesBean.isWorldNewsInterest()) { %>
|
<% if(propertiesBean.isWorldNewsInterest()) { %>
|
||||||
<td><%@include file="worldNews.jsp"%></td>
|
<td><%@include file="worldNews.jsp"%></td>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<td><%@include file="localNews.jsp"%></td>
|
<td><%@include file="localNews.jsp"%></td>
|
||||||
<% } %>
|
<% } %>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<% if(propertiesBean.isBusinessInterest()) { %>
|
<% if(propertiesBean.isBusinessInterest()) { %>
|
||||||
<td><%@include file="businessNews.jsp"%></td>
|
<td><%@include file="businessNews.jsp"%></td>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<td><%@include file="localNews.jsp"%></td>
|
<td><%@include file="localNews.jsp"%></td>
|
||||||
<% } %>
|
<% } %>
|
||||||
<td></td>
|
<td></td>
|
||||||
<% if(propertiesBean.isSportsInterest()) { %>
|
<% if(propertiesBean.isSportsInterest()) { %>
|
||||||
<td><%@include file="sportsNews.jsp"%></td>
|
<td><%@include file="sportsNews.jsp"%></td>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<td><%@include file="localNews.jsp"%></td>
|
<td><%@include file="localNews.jsp"%></td>
|
||||||
<% } %>
|
<% } %>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<% if(propertiesBean.isScienceNewsInterest()) { %>
|
<% if(propertiesBean.isScienceNewsInterest()) { %>
|
||||||
<td><%@include file="scienceNews.jsp"%></td>
|
<td><%@include file="scienceNews.jsp"%></td>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<td><%@include file="localNews.jsp"%></td>
|
<td><%@include file="localNews.jsp"%></td>
|
||||||
<% } %>
|
<% } %>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
This JSP page is the template. It declares a table with three rows, with one component in the first row,
|
This JSP page is the template. It declares a table with three rows, with one component in the first row,
|
||||||
two components in the second row, and one component in the third row.
|
two components in the second row, and one component in the third row.
|
||||||
|
|
||||||
@@ -203,65 +231,83 @@ view management strategy that include different atomic subviews based on the use
|
|||||||
|
|
||||||
Here are two examples of the mock atomic subviews used in the composite:
|
Here are two examples of the mock atomic subviews used in the composite:
|
||||||
`businessNews.jsp`
|
`businessNews.jsp`
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
h2 { text-align: center;}
|
h2 {
|
||||||
table {border: 1px solid black;}
|
text-align: center;
|
||||||
tr {text-align: center;}
|
}
|
||||||
td {text-align: center;}
|
|
||||||
</style>
|
table {
|
||||||
</head>
|
border: 1px solid black;
|
||||||
<body>
|
}
|
||||||
<h2>
|
|
||||||
Generic Business News
|
tr {
|
||||||
</h2>
|
text-align: center;
|
||||||
<table style="margin-right: auto; margin-left: auto">
|
}
|
||||||
<tr>
|
|
||||||
<td>Stock prices up across the world</td>
|
td {
|
||||||
<td>New tech companies to invest in</td>
|
text-align: center;
|
||||||
</tr>
|
}
|
||||||
<tr>
|
</style>
|
||||||
<td>Industry leaders unveil new project</td>
|
</head>
|
||||||
<td>Price fluctuations and what they mean</td>
|
<body>
|
||||||
</tr>
|
<h2>
|
||||||
</table>
|
Generic Business News
|
||||||
</body>
|
</h2>
|
||||||
|
<table style="margin-right: auto; margin-left: auto">
|
||||||
|
<tr>
|
||||||
|
<td>Stock prices up across the world</td>
|
||||||
|
<td>New tech companies to invest in</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Industry leaders unveil new project</td>
|
||||||
|
<td>Price fluctuations and what they mean</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
`localNews.jsp`
|
`localNews.jsp`
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
<h3>
|
<h3>
|
||||||
Generic Local News
|
Generic Local News
|
||||||
</h3>
|
</h3>
|
||||||
<ul style="list-style-type: none">
|
<ul style="list-style-type: none">
|
||||||
<li>
|
<li>
|
||||||
Mayoral elections coming up in 2 weeks
|
Mayoral elections coming up in 2 weeks
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
New parking meter rates downtown coming tomorrow
|
New parking meter rates downtown coming tomorrow
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Park renovations to finish by the next year
|
Park renovations to finish by the next year
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Annual marathon sign ups available online
|
Annual marathon sign ups available online
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
The results are as such:
|
The results are as such:
|
||||||
|
|
||||||
1) The user has put their name as `Tammy` in the request parameters and no preferences:
|
1) The user has put their name as `Tammy` in the request parameters and no preferences:
|
||||||

|

|
||||||
2) The user has put their name as `Johnny` in the request parameters and has a preference for world, business, and science news:
|
2) The user has put their name as `Johnny` in the request parameters and has a preference for world, business, and
|
||||||

|
science news:
|
||||||
|

|
||||||
|
|
||||||
The different subviews such as `worldNews.jsp`, `businessNews.jsp`, etc. are included conditionally
|
The different subviews such as `worldNews.jsp`, `businessNews.jsp`, etc. are included conditionally
|
||||||
based on the request parameters.
|
based on the request parameters.
|
||||||
@@ -277,7 +323,8 @@ Under `Run` and `edit configurations` Make sure Tomcat server is one of the run
|
|||||||
Go to the deployment tab, and make sure there is one artifact being built called `composite-view:war exploded`.
|
Go to the deployment tab, and make sure there is one artifact being built called `composite-view:war exploded`.
|
||||||
If not present, add one.
|
If not present, add one.
|
||||||
|
|
||||||
Ensure that the artifact is being built from the content of the `web` directory and the compilation results of the module.
|
Ensure that the artifact is being built from the content of the `web` directory and the compilation results of the
|
||||||
|
module.
|
||||||
Point the output of the artifact to a convenient place. Run the configuration and view the landing page,
|
Point the output of the artifact to a convenient place. Run the configuration and view the landing page,
|
||||||
follow instructions on that page to continue.
|
follow instructions on that page to continue.
|
||||||
|
|
||||||
@@ -288,35 +335,52 @@ follow instructions on that page to continue.
|
|||||||
The class diagram here displays the Javabean which is the view manager.
|
The class diagram here displays the Javabean which is the view manager.
|
||||||
The views are JSP's held inside the web directory.
|
The views are JSP's held inside the web directory.
|
||||||
|
|
||||||
## Applicability
|
## Applicability:
|
||||||
|
|
||||||
This pattern is applicable to most websites that require content to be displayed dynamically/conditionally.
|
Use the Composite View design pattern when:
|
||||||
If there are components that need to be re-used for multiple views, or if the project requires reusing a template,
|
|
||||||
or if it needs to include content depending on certain conditions, then this pattern is a good choice.
|
|
||||||
|
|
||||||
## Known uses
|
* You want to represent part-whole hierarchies of objects.
|
||||||
|
* You expect that the composite structures might include any new components in the future.
|
||||||
|
* You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients
|
||||||
|
will treat all objects in the composite structure uniformly.
|
||||||
|
|
||||||
Most modern websites use composite views in some shape or form, as they have templates for views and small atomic components
|
## Known Uses
|
||||||
that are included in the page dynamically. Most modern Javascript libraries, like React, support this design pattern
|
|
||||||
with components.
|
* Graphical User Interfaces (GUIs) where widgets can contain other widgets (e.g., a window containing panels, buttons,
|
||||||
|
and text fields).
|
||||||
|
* Document structures, such as the representation of tables containing rows, which in turn contain cells, all of which
|
||||||
|
can be treated as elements in a unified hierarchy.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
**Pros**
|
|
||||||
* Easy to re-use components
|
|
||||||
* Change layout/content without affecting the other
|
|
||||||
* Reduce code duplication
|
|
||||||
* Code is more maintainable and modular
|
|
||||||
|
|
||||||
**Cons**
|
Benefits:
|
||||||
* Overhead cost at runtime
|
|
||||||
* Slower response compared to directly embedding elements
|
|
||||||
* Increases potential for display errors
|
|
||||||
|
|
||||||
## Related patterns
|
* High flexibility in adding new components: Since composites and leaf nodes are treated uniformly, it's easier to add
|
||||||
* [Composite (GoF)](https://java-design-patterns.com/patterns/composite/)
|
new kinds of components.
|
||||||
|
* Simplified client code: Clients can treat composite structures and individual elements uniformly, reducing the
|
||||||
|
complexity in client code.
|
||||||
|
|
||||||
|
Trade-offs:
|
||||||
|
|
||||||
|
* Overgeneralization: Designing the system might become more complex if you make everything composite, especially if
|
||||||
|
your application doesn't require it.
|
||||||
|
* Difficulty in constraint enforcement: It can be harder to restrict the components of a composite to only certain
|
||||||
|
types.
|
||||||
|
|
||||||
|
## Related Patterns
|
||||||
|
|
||||||
|
* [Decorator](https://java-design-patterns.com/patterns/decorator/): While Decorator is used to add responsibilities to
|
||||||
|
objects, Composite is meant for building structures of objects.
|
||||||
|
* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can often be combined with Flyweight to
|
||||||
|
implement shared leaf nodes in a composite structure, reducing the memory footprint.
|
||||||
|
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Can be used with
|
||||||
|
Composite to let components pass requests through the hierarchy.
|
||||||
|
* [Composite](https://java-design-patterns.com/patterns/composite/)
|
||||||
* [View Helper](https://www.oracle.com/java/technologies/viewhelper.html)
|
* [View Helper](https://www.oracle.com/java/technologies/viewhelper.html)
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
* [Core J2EE Patterns - Composite View](https://www.oracle.com/java/technologies/composite-view.html)
|
* [Core J2EE Patterns - Composite View](https://www.oracle.com/java/technologies/composite-view.html)
|
||||||
* [Composite View Design Pattern – Core J2EE Patterns](https://www.dineshonjava.com/composite-view-design-pattern/)
|
* [Composite View Design Pattern – Core J2EE Patterns](https://www.dineshonjava.com/composite-view-design-pattern/)
|
||||||
|
* [Patterns of Enterprise Application Architecture](https://amzn.to/49jpQG3)
|
||||||
|
* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3xfntGJ)
|
||||||
Reference in new issue
Block a user