组合在 Java 中的实现

article/2025/10/4 17:39:37

组合是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。

对于绝大多数需要生成树状结构的问题来说, 组合都是非常受欢迎的解决方案。 组合最主要的功能是在整个树状结构上递归调用方法并对结果进行汇总。

在 Java 中使用模式

复杂度:⭐⭐

流行度:⭐⭐

使用实例: 组合模式在 Java 代码中很常见,常用于表示与图形打交道的用户界面组件或代码的层次结构。

下面是一些来自 Java 标准程序库中的组合示例:

  • java.awt.Container#add(Component) (几乎广泛存在于 Swing 组件中)

  • javax.faces.component.UIComponent#getChildren() (几乎广泛存在于 JSF UI 组件中)

识别方法: 组合可以通过将同一抽象或接口类型的实例放入树状结构的行为方法来轻松识别。

shapes

 shapes/Shape.java: 通用形状接口

package refactoring_guru.composite.example.shapes;import java.awt.*;public interface Shape {int getX();int getY();int getWidth();int getHeight();void move(int x, int y);boolean isInsideBounds(int x, int y);void select();void unSelect();boolean isSelected();void paint(Graphics graphics);
}

 shapes/BaseShape.java: 提供基本功能的抽象形状

package refactoring_guru.composite.example.shapes;import java.awt.*;abstract class BaseShape implements Shape {public int x;public int y;public Color color;private boolean selected = false;BaseShape(int x, int y, Color color) {this.x = x;this.y = y;this.color = color;}@Overridepublic int getX() {return x;}@Overridepublic int getY() {return y;}@Overridepublic int getWidth() {return 0;}@Overridepublic int getHeight() {return 0;}@Overridepublic void move(int x, int y) {this.x += x;this.y += y;}@Overridepublic boolean isInsideBounds(int x, int y) {return x > getX() && x < (getX() + getWidth()) &&y > getY() && y < (getY() + getHeight());}@Overridepublic void select() {selected = true;}@Overridepublic void unSelect() {selected = false;}@Overridepublic boolean isSelected() {return selected;}void enableSelectionStyle(Graphics graphics) {graphics.setColor(Color.LIGHT_GRAY);Graphics2D g2 = (Graphics2D) graphics;float dash1[] = {2.0f};g2.setStroke(new BasicStroke(1.0f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,2.0f, dash1, 0.0f));}void disableSelectionStyle(Graphics graphics) {graphics.setColor(color);Graphics2D g2 = (Graphics2D) graphics;g2.setStroke(new BasicStroke());}@Overridepublic void paint(Graphics graphics) {if (isSelected()) {enableSelectionStyle(graphics);}else {disableSelectionStyle(graphics);}// ...}
}

 shapes/Dot.java: 点

package refactoring_guru.composite.example.shapes;import java.awt.*;public class Dot extends BaseShape {private final int DOT_SIZE = 3;public Dot(int x, int y, Color color) {super(x, y, color);}@Overridepublic int getWidth() {return DOT_SIZE;}@Overridepublic int getHeight() {return DOT_SIZE;}@Overridepublic void paint(Graphics graphics) {super.paint(graphics);graphics.fillRect(x - 1, y - 1, getWidth(), getHeight());}
}

 shapes/Circle.java: 圆形

package refactoring_guru.composite.example.shapes;import java.awt.*;public class Circle extends BaseShape {public int radius;public Circle(int x, int y, int radius, Color color) {super(x, y, color);this.radius = radius;}@Overridepublic int getWidth() {return radius * 2;}@Overridepublic int getHeight() {return radius * 2;}public void paint(Graphics graphics) {super.paint(graphics);graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1);}
}

 shapes/Rectangle.java: 三角形

package refactoring_guru.composite.example.shapes;import java.awt.*;public class Rectangle extends BaseShape {public int width;public int height;public Rectangle(int x, int y, int width, int height, Color color) {super(x, y, color);this.width = width;this.height = height;}@Overridepublic int getWidth() {return width;}@Overridepublic int getHeight() {return height;}@Overridepublic void paint(Graphics graphics) {super.paint(graphics);graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1);}
}

 shapes/CompoundShape.java: 由其他形状对象组成的复合形状

package refactoring_guru.composite.example.shapes;import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class CompoundShape extends BaseShape {protected List<Shape> children = new ArrayList<>();public CompoundShape(Shape... components) {super(0, 0, Color.BLACK);add(components);}public void add(Shape component) {children.add(component);}public void add(Shape... components) {children.addAll(Arrays.asList(components));}public void remove(Shape child) {children.remove(child);}public void remove(Shape... components) {children.removeAll(Arrays.asList(components));}public void clear() {children.clear();}@Overridepublic int getX() {if (children.size() == 0) {return 0;}int x = children.get(0).getX();for (Shape child : children) {if (child.getX() < x) {x = child.getX();}}return x;}@Overridepublic int getY() {if (children.size() == 0) {return 0;}int y = children.get(0).getY();for (Shape child : children) {if (child.getY() < y) {y = child.getY();}}return y;}@Overridepublic int getWidth() {int maxWidth = 0;int x = getX();for (Shape child : children) {int childsRelativeX = child.getX() - x;int childWidth = childsRelativeX + child.getWidth();if (childWidth > maxWidth) {maxWidth = childWidth;}}return maxWidth;}@Overridepublic int getHeight() {int maxHeight = 0;int y = getY();for (Shape child : children) {int childsRelativeY = child.getY() - y;int childHeight = childsRelativeY + child.getHeight();if (childHeight > maxHeight) {maxHeight = childHeight;}}return maxHeight;}@Overridepublic void move(int x, int y) {for (Shape child : children) {child.move(x, y);}}@Overridepublic boolean isInsideBounds(int x, int y) {for (Shape child : children) {if (child.isInsideBounds(x, y)) {return true;}}return false;}@Overridepublic void unSelect() {super.unSelect();for (Shape child : children) {child.unSelect();}}public boolean selectChildAt(int x, int y) {for (Shape child : children) {if (child.isInsideBounds(x, y)) {child.select();return true;}}return false;}@Overridepublic void paint(Graphics graphics) {if (isSelected()) {enableSelectionStyle(graphics);graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1);disableSelectionStyle(graphics);}for (refactoring_guru.composite.example.shapes.Shape child : children) {child.paint(graphics);}}
}

 editor

 editor/ImageEditor.java: 形状编辑器

package refactoring_guru.composite.example.editor;import refactoring_guru.composite.example.shapes.CompoundShape;
import refactoring_guru.composite.example.shapes.Shape;import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class ImageEditor {private EditorCanvas canvas;private CompoundShape allShapes = new CompoundShape();public ImageEditor() {canvas = new EditorCanvas();}public void loadShapes(Shape... shapes) {allShapes.clear();allShapes.add(shapes);canvas.refresh();}private class EditorCanvas extends Canvas {JFrame frame;private static final int PADDING = 10;EditorCanvas() {createFrame();refresh();addMouseListener(new MouseAdapter() {@Overridepublic void mousePressed(MouseEvent e) {allShapes.unSelect();allShapes.selectChildAt(e.getX(), e.getY());e.getComponent().repaint();}});}void createFrame() {frame = new JFrame();frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);frame.setLocationRelativeTo(null);JPanel contentPanel = new JPanel();Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING);contentPanel.setBorder(padding);frame.setContentPane(contentPanel);frame.add(this);frame.setVisible(true);frame.getContentPane().setBackground(Color.LIGHT_GRAY);}public int getWidth() {return allShapes.getX() + allShapes.getWidth() + PADDING;}public int getHeight() {return allShapes.getY() + allShapes.getHeight() + PADDING;}void refresh() {this.setSize(getWidth(), getHeight());frame.pack();}public void paint(Graphics graphics) {allShapes.paint(graphics);}}
}

 Demo.java: 客户端代码

package refactoring_guru.composite.example;import refactoring_guru.composite.example.editor.ImageEditor;
import refactoring_guru.composite.example.shapes.Circle;
import refactoring_guru.composite.example.shapes.CompoundShape;
import refactoring_guru.composite.example.shapes.Dot;
import refactoring_guru.composite.example.shapes.Rectangle;import java.awt.*;public class Demo {public static void main(String[] args) {ImageEditor editor = new ImageEditor();editor.loadShapes(new Circle(10, 10, 10, Color.BLUE),new CompoundShape(new Circle(110, 110, 50, Color.RED),new Dot(160, 160, Color.RED)),new CompoundShape(new Rectangle(250, 250, 100, 100, Color.GREEN),new Dot(240, 240, Color.GREEN),new Dot(240, 360, Color.GREEN),new Dot(360, 360, Color.GREEN),new Dot(360, 240, Color.GREEN)));}
}

 OutputDemo.png: 执行结果


http://chatgpt.dhexx.cn/article/4Cp3yxC6.shtml

相关文章

extras mibs php7,Ubuntu 14.04中PHP命令行找不到MIBS的提示信息

安装了php的Ubuntu 14.04服务器每半小时会执行一次/etc/cron.d/php5脚本&#xff0c;清理超时的php会话文件。由于找不到snmp mibs文件&#xff0c;php命令行解释器启动时会吐出一堆提示信息&#xff0c;这些信息会被Cron Daemon通过Email发送给root用户。日积月累这些无意义的…

Salesforce从业者最重要的6个基础认证!

Salesforce认证一直备受业内人士的重视&#xff0c;拥有值得信赖的含金量。成为Salesforce认证专家不仅表明了专业技能的熟练程度&#xff0c;也是对个人和专业发展的保障。 此外&#xff0c;大多数Salesforce从业者都至少持有一项认证&#xff0c;并且自由侠部落之前发布的薪…

Salesforce项目文档收集

集少成多&#xff01; #3 Event Monitoring Architecture Ref: Salesforce event monitoring — under the hood #2 Capability Map Business Capability Map CPQ Capability Map #1 CPQ Product Data Migration Schema 意义&#xff1a; Question List:

多方面比较Salesforce与Microsoft Dynamics 365

这是Salesforce和Microsoft Dynamics™365的基于事实的比较。对于那些为正在准备上CRM的公司来说&#xff0c;以下信息是一点提示。 此篇文章并不是要比较出来哪个产品更优秀&#xff0c;只是给CRM从业者一个提示来看到两个产品不同的特性。 本文中的分析主要侧重于开箱即用的功…

【科普干货】一张图看懂Salesforce最新产品结构

放眼全世界&#xff0c;当今最具影响力的云CRM供应商当属Salesforce已经完全没有争议了。可以说Salesforce是在全球普及SaaS模式企业应用的第一功臣&#xff0c;并且Salesforce在本世纪初也已超越了销售自动化和CRM的范畴&#xff0c;通过不断的自研和收购提供了一揽子可以满足…

2022年N1叉车司机操作证考试题模拟考试平台操作

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2022年N1叉车司机培训试题为N1叉车司机模拟考试题库上机考试练习题&#xff01;2022年N1叉车司机操作证考试题模拟考试平台操作根据N1叉车司机新版考试题库。N1叉车司机考试模拟题通过安全生产模拟考试一点通学习进度…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java酒店客房管理系统cpq7c

计算机毕业设计的编程真的不会, 应该怎么办啊, 平时学了3年都没学懂&#xff0c;然而还有一个月就要答辩了&#xff0c;一点东西都没做出来&#xff0c;不知道该怎么办了&#xff1f;好迷茫&#xff0c;如果毕不到业怎么办, 有没有快速的学习方法 毕设毕设&#xff0c;最终的是…

ssm毕设项目酒店客房管理系统cpq7c(java+VUE+Mybatis+Maven+Mysql+sprnig)

ssm毕设项目酒店客房管理系统cpq7c&#xff08;javaVUEMybatisMavenMysqlsprnig&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&…

5款CPQ报价管理系统测评,哪个值得用?

CPQ的全称是Configure&#xff08;配置&#xff09; Price&#xff08;价格&#xff09; Quote&#xff08;报价&#xff09;&#xff0c;是用来配置报价的软件&#xff0c;多用于B2B业务场景&#xff0c;例如装备制造业&#xff0c;帮助卖方对复杂的、可配置的产品进行报价。 …

Salesforce CPQ:如何实现复杂产品配置和报价?

每当你的客户向你询问报价的时候&#xff0c;他们其实是在询问潜在的购买信息&#xff0c;如他们将会用多少钱买到什么东西。我们可能会用打印的报价单&#xff0c;一个邮件或一个电话来提供给客户报价信息。对于报价这个词可能不同的人有不同的理解&#xff0c;让我们花些时间…

CPQ技术能简化制造业的销售过程

复杂产品的制造业企业在产品销售过程中面临着很大的挑战&#xff1a;如何生成准确的报价并生成订单。 因产品类型或可配置导致有多个类型&#xff0c;经常被复杂的操作所限制&#xff0c;复杂的配置规则和利润计算拖慢了报价的进程&#xff0c;容易让销售人员和客户都感到焦急。…

CPQ软件如何简化制造业的复杂销售过程

复杂产品的制造业企业在产品销售过程中面临着很大的挑战&#xff1a;如何生成准确的报价并生成订单。 因产品类型或可配置导致有多个类型&#xff0c;经常被复杂的操作所限制&#xff0c;复杂的配置规则和利润计算拖慢了报价的进程&#xff0c;容易让销售人员和客户都感到焦急…

SAP 电商云 Spartacus UI 和 CPQ Configurable Products 的集成

CPQ 可配置产品集成在 Spartacus 中提供了一个用户界面&#xff0c;用于配置和销售已使用 SAP CPQ 可配置产品集成和相关配置引擎建模的可配置产品。请注意&#xff0c;Spartacus 库不包括 SAP CPQ 本身。 用于可配置产品的 SAP CPQ 集成的 Spartacus 库的初始版本包括以下功能…

什么是CPQ,以及为什么选择Salesforce

你和你的销售团队希望更快的赢得交易&#xff0c;这是你使用Salesforce的一个原因。这也是一个很好的理由花时间学习CPQ的原因&#xff0c;在这里你会了解Salesforce CPQ&#xff0c;这是一个原生的Salesforce应用程序&#xff08;在Force.com平台上开发的CPQ产品&#xff0c;后…

Enhanced CPQ solution from In Mind Cloud CPQ Express 1711

engineer to order 在這種生產類型下&#xff0c;一種產品在很大程度上是按照某一特定客戶的要求來設計的&#xff0c;所以說支持客戶化的設計是該生產流程的重要功能和組成部分。因為絕大多數產品都是為特定客戶度身定製&#xff0c;所以這些產品可能只生產一次&#xff0c;以…

CPQ-装备制造企业需求到报价转化效率提升的利器

在装备制造企业中&#xff0c;需求到报价的转化效率低一直是阻碍销售业务增长的难题。在定制化商品的销售过程中&#xff0c;销售人员需要根据客户的需求进行灵活的产品选型、产品配置和价格制定。然而&#xff0c;装备制造企业往往有大量的产品型号、高度配置化的配置项和复杂…

CPQ 注意事项

1.经常.id取不到值&#xff0c;最好要大写I&#xff0c;如图写; Application Event 事件获取不到问题&#xff1a;错误信息&#xff1a;Cannot read property setParams of undefined 之前代码如图&#xff1a; onRefresh 事件一直是undefined&#xff0c;因为baseSvc是自定义…

什么是CPQ?以及为什么选择Salesforce?

你和你的销售团队希望更快的赢得交易&#xff0c;这是你使用Salesforce的一个原因。这也是一个很好的理由花时间学习CPQ的原因&#xff0c;在这里你会了解Salesforce CPQ&#xff0c;这是一个原生的Salesforce应用程序&#xff08;在Force.com平台上开发的CPQ产品&#xff0c;后…

【数字化销售】CPQ软件概述

什么是CPQ软件&#xff1f; 配置、定价、报价&#xff08;CPQ&#xff09;软件是一种销售加速软件&#xff0c;主要用于生成报价和管理产品配置请求。这简化了销售活动&#xff0c;为客户提供了快速和准确的定价信息&#xff0c;根据他们的需要。 该软件根据一组定义的规则自动…

什么是面包屑导航?

面包屑导航用来辅助主导航&#xff0c;一般在页面的上方。 例子: 苹果使用面包屑导航辅助展示主导航