Java 组合模式讲解和代码示例

简介: Java 组合模式讲解和代码示例

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

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

  • java.awt.Container#add(Component)几乎广泛存在于 Swing 组件中
  • javax.faces.component.UIComponent#getChildren()几乎广泛存在于 JSF UI 组件中

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

01简单和复合图形


本例展示了如何利用较为简单的形状来组成复杂图形 以及如何统一处理简单和复杂图形


02shapes

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;
    }


 

@Override
    public int getX() {
        return x;
    }
    @Override
    public int getY() {
        return y;
    }
    @Override
    public int getWidth() {
        return 0;
    }
    @Override
    public int getHeight() {
        return 0;
    }
    @Override
    public void move(int x, int y) {
        this.x += x;
        this.y += y;
    }
    @Override
    public boolean isInsideBounds(int x, int y) {
        return x > getX() && x < (getX() + getWidth()) &&
                y > getY() && y < (getY() + getHeight());
    }
    @Override
    public void select() {
        selected = true;
    }
    @Override
    public void unSelect() {
        selected = false;
    }
    @Override
    public 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());
    }
    @Override
    public 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);
    }
    @Override
    public int getWidth() {
        return DOT_SIZE;
    }
    @Override
    public int getHeight() {
        return DOT_SIZE;
    }
    @Override
    public 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;
    }
    @Override
    public int getWidth() {
        return radius * 2;
    }
    @Override
    public 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;
    }
    @Override
    public int getWidth() {
        return width;
    }
    @Override
    public int getHeight() {
        return height;
    }
    @Override
    public 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();
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public 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;
    }
    @Override
    public void move(int x, int y) {
        for (Shape child : children) {
            child.move(x, y);
        }
    }
    @Override
    public boolean isInsideBounds(int x, int y) {
        for (Shape child : children) {
            if (child.isInsideBounds(x, y)) {
                return true;
            }
        }
        return false;
    }
    @Override
    public 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;
    }
    @Override
    public 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);
        }
    }
}


03editor


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() {
                @Override
                public 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: 执行结果


以上是Java 组合模式讲解和代码示例文章!

相关文章
|
5天前
|
Java 索引
String字符串常用函数以及示例 JAVA基础
String字符串常用函数以及示例 JAVA基础
|
6天前
|
Java 程序员 图形学
程序员教你用代码制作飞翔的小鸟--Java小游戏,正好拿去和给女神一起玩
《飞扬的小鸟》Java实现摘要:使用IntelliJ IDEA和JDK 16开发,包含小鸟类`Bird`,处理小鸟的位置、速度和碰撞检测。代码示例展示小鸟图像的加载、绘制与旋转。同时有`Music`类用于循环播放背景音乐。游戏运行时检查小鸟是否撞到地面、柱子或星星,并实现翅膀煽动效果。简单易懂,可直接复制使用。
|
2天前
|
Java 测试技术
如何提高Java代码的可读性
Java是一种常用的编程语言,但是写出易懂且可读性高的代码却是一项挑战。本文将分享一些技巧和建议,帮助您提高Java代码的可读性和可维护性。
|
5天前
|
Java Kotlin
java调用kotlin代码编译报错“找不到符号”的问题
java调用kotlin代码编译报错“找不到符号”的问题
17 10
|
6天前
|
前端开发 Java Spring
Java Web ——MVC基础框架讲解及代码演示(下)
Java Web ——MVC基础框架讲解及代码演示
13 1
|
6天前
|
设计模式 前端开发 网络协议
Java Web ——MVC基础框架讲解及代码演示(上)
Java Web ——MVC基础框架讲解及代码演示
8 0
|
6天前
|
Java
Java的取余如何编写代码
【5月更文挑战第9天】Java的取余如何编写代码
22 5
|
6天前
|
Java
代码实例演示Java字符串与输入流互转
代码实例演示Java字符串与输入流互转
10 1
|
6天前
|
存储 安全 Java
掌握8条泛型规则,打造优雅通用的Java代码
掌握8条泛型规则,打造优雅通用的Java代码
掌握8条泛型规则,打造优雅通用的Java代码
|
6天前
|
数据库连接
java+ssm+vue代码视频学习讲解
java+ssm+vue代码视频学习讲解
11 0