设计模式原型模式
原型模式概述
原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。
通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,通常对克隆所产生的对象进行修改对原型对象不会造成任何影响,每一个克隆对象都是相互独立的。 原型模式的类结构
Client(客户端):客户端提出创建对象的请求。让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。 Prototype(原型接口类):它是声明克隆方法的接口,是所有原型实现类的公共父类。 ConcretePrototype(原型实现类):它实现在原型接口类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
从类到对象叫"创建",而由本体对象到副本对象则叫"克隆"。当需要创建多个类似的复杂对象时,我们就可以考虑使用原型模式。
原型模式的核心在于如何实现克隆方法。 原型模式的应用场景
原型模式主要适用于以下应用场景。
(1)创建对象成本较大(例如,初始化时间长,占用CPU太多,或者占用网络资源太多等),需要优化资源。
(2)创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。
(3)系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。 原型模式的代码实现
效果图预览
图片中的所有圆点和五角星都是通过调用clone()方法创建的。
Shape.java
图形类,对应原型模式中的Prototype。 /** * 原型接口 */ public interface Shape extends Cloneable { Shape clone(); void draw(Graphics g); }
Circle.java
圆形类,对应原型模式中的ConcretePrototype。 /** * 原型实现类:圆形 */ @Data @NoArgsConstructor public class Circle implements Shape { /** x轴位置 */ private int x; /** y轴位置 */ private int y; @Override public Circle clone() { Circle clone = null; try { clone = (Circle)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } @Override public void draw(Graphics g) { Graphics2D g2d = (Graphics2D) g; Ellipse2D.Double circle = new Ellipse2D.Double(this.getX(), this.getY(), 10, 10); g2d.setColor(Color.RED); g2d.fill(circle); } }
Star.java
五角星类,对应原型模式中的ConcretePrototype。 /** * 原型实现类:五角星 */ @Data @NoArgsConstructor public class Star implements Shape { /** x轴位置 */ private int x; /** y轴位置 */ private int y; @Override public Star clone() { Star clone = null; try { clone = (Star) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } @Override public void draw(Graphics g) { int xPoints[] = {9, 15, 0, 18, 3}; int yPoints[] = {0, 18, 6, 6, 18}; Graphics2D g2d = (Graphics2D) g; GeneralPath star = new GeneralPath(); star.moveTo(xPoints[0] + this.getX(), yPoints[0] + this.getY()); for (int i = 1; i < xPoints.length; i++) { star.lineTo(xPoints[i] + this.getX(), yPoints[i] + this.getY()); } star.closePath(); g2d.setColor(Color.ORANGE); g2d.fill(star); } }
ShapeFactory.java public class ShapeFactory { private static Circle circle = new Circle(); private static Star star = new Star(); public static Shape getInstance(String shapeType, int x, int y) { if (Objects.equals("circle", shapeType)) { Circle cloneCircle = circle.clone(); cloneCircle.setX(x); cloneCircle.setY(y); return cloneCircle; } else if (Objects.equals("star", shapeType)) { Star cloneStar = star.clone(); cloneStar.setX(x); cloneStar.setY(y); return cloneStar; } return null; } }
PrototypePanel.java
面板类,用于绘制图形并展示。 public class PrototypePanel extends JPanel { private List shapeList = new ArrayList<>(); public PrototypePanel() { // 设置背景颜色:白色 setBackground(Color.LIGHT_GRAY); // 设置面板大小: 500 * 500 setPreferredSize(new Dimension(500, 500)); for(int i = 0; i < 20; i++) { Random random = new Random(); shapeList.add(ShapeFactory.getInstance("circle", random.nextInt(500), random.nextInt(500))); } for(int i = 0; i < 20; i++) { Random random = new Random(); shapeList.add(ShapeFactory.getInstance("star", random.nextInt(500), random.nextInt(500))); } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); for (Shape shape : shapeList) { if (shape instanceof Circle) { shape.draw(g); } else if (shape instanceof Star) { shape.draw(g); } } } public static void main(String[] args) { JFrame jFrame = new JFrame(); jFrame.add(new PrototypePanel()); jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame.pack(); jFrame.setLocationRelativeTo(null); jFrame.setVisible(true); } }深拷贝和浅拷贝
Java中的变量分为原始类型和引用类型。
浅拷贝是指只复制原始类型的值。引用类型同样会被拷贝,但是只是拷贝了地址引用。