原型模式-Prototype
通过复制(克隆、拷贝)一个指定类型的对象来创建更多同类型的对象.
就像去蛋糕店买蛋糕一样. 柜台里的蛋糕都是非卖品. 只是为顾客提供一种参照. 当顾客看上某一个样式的蛋糕后. 蛋糕师就会为顾客新做一份一模一样的.
这样就可以说明为什么要有prototype模型, 而不是每次都重新new一个了.
因为每次都重新new一个的话, 代表着蛋糕要从设计到制作都要现场完成. 这时很困难的.
如果有一个原型的话. 蛋糕师就可以根据这个模板, 来参照着做出一个一模一样的. 显然这样的难度降低了很多.
卖笔和卖蛋糕的原理是一样的.本文以笔为例.
有一个管理类UnderLinePenManager, 里面有三种笔. 第一种能画波浪线, 第二种能画直线, 第三种能画虚线.
如果有人想要这三种里的某一种. 那么就根据管理类里已经注册好的模板来新建一个一样的笔出来.
本例子中的类关系图:
类的依赖关系:
Product接口
我们将使用原型模式来创建对象, 而这些对象, 就被抽象为Product
Product还提供了复制方法createClone(). 继承了Cloneable接口.
注意: 这里的createClone()方法并不是继承于Cloneable, Cloneable里面并没有声明任何方法, Cloneable只是起标记作用的一个接口.
public interface Product extends Cloneable { void use(String str); Product createClone(); }
UnderlinePen类
这是Product接口的实现类, 下划线类.
向特定的下划线类传入一个字符串后, 他会打印出该字符串和下划线
public class UnderLinePen implements Product { /** * 下划线字符 */ private char underLineChar; public UnderLinePen(char ch) { this.underLineChar = ch; } /** * 传入str后, 会打印str和下划线 */ @Override public void use(String str) { System.out.println(""" + str + """); System.out.print(" "); for (int i = 0; i < str.getBytes().length; i++) { System.out.print(underLineChar); } System.out.println(""); } /** * 返回一个克隆 */ @Override public Product createClone() { try { return (Product) this.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } }
UnderLinePenManager类
用于统一管理产品, 他来负责注册和克隆
public class UnderLinePenManager { /** * 各种笔注册到这里, 统一管理 */ private static final HashMap<String, Product> PENS = new HashMap<>(); /** * 注册笔 */ public static void register(String name, Product pen) { PENS.put(name, pen); } /** * 从注册中心HashMap以name为key取出来一只笔, 然后克隆一个新的来返回 */ public static Product createPen(String name) { return PENS.get(name).createClone(); } }
Main
该类用于运行测试
public class Main { static { /** * 将各种笔注册到Manager来统一管理 */ UnderLinePenManager.register("wave-line" , new UnderLinePen('~')); UnderLinePenManager.register("bee-line" , new UnderLinePen('_')); UnderLinePenManager.register("dotted-line", new UnderLinePen('.')); } public static void main(String[] args) { // 每次需要某种笔的时候, 根据现有的笔来进行克隆一份就好了 // 取出一只波浪线的笔 Product anotherPen1 = UnderLinePenManager.createPen("wave-line"); // 用波浪线的笔来打印 anotherPen1.use("hello world"); } }