Prototype(原型)模式的由来

创建一个实例,可以关键字new创建。但有时候,我们需要在不指定类名的前提下生成实例,比如:

  • 需要处理的对象种类繁多,无法整合到一个类里面,如果分别作为一个类,类的数量又太多了。

  • 很难通过代码生成实例:比如用户在画图工具中画出来的图形实例,如果用代码创建的话是非常困难的。我们可以先保存起来,需要时通过复制生成实例。

  • 想解耦框架和生成的实例时:不指定类名来生成实例,而是事先注册一个原型实例,通过复制该实例来生成新实例。比如打印机,不需要知道具体的文档内容,到需要的时候复印就行了,复印多少次都没问题。

类图

代码

Product接口,继承Cloneable接口,实现Product接口的类都可以使用clone方法进行实例的复制。

use方法表示怎么使用,具体怎么用,由子类来实现。

createClone是用于复制实例的方法。

public interface Product extends Cloneable {
public abstract void use(String s);
public abstract Product createClone();
}

Manager类,需要生成对象的类可以调用Manager类的create方法复制实例

public class Manager {
private HashMap showcase = new HashMap();
public void register(String name, Product proto) {
showcase.put(name, proto);
}
public Product create(String protoname) {
Product p = (Product) showcase.get(protoname);
return p.createClone();
}
}

具体要进行对象复制的类

public class MessageBox implements Product {
private char decochar;
public MessageBox(char decochar) {
this.decochar = decochar;
} @Override
public void use(String s) {
int length = s.getBytes().length;
for (int i = 0; i < length+4; i++) {
System.out.print(decochar);
}
System.out.println("");
System.out.println(decochar + " " + s + " " + decochar);
for (int i = 0; i < length+4; i++) {
System.out.print(decochar);
}
System.out.println("");
} @Override
public Product createClone() {
Product p = null;
try {
p = (Product)clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
} public class UnderlinePen implements Product {
private char ulchar;
public UnderlinePen(char ulchar) {
this.ulchar = ulchar;
}
@Override
public void use(String s) {
int length = s.getBytes().length;
System.out.println("\"" + s + "\"");
System.out.print(" ");
for (int i = 0; i < length; i++) {
System.out.print(ulchar);
}
System.out.println("");
} @Override
public Product createClone() {
Product p = null;
try {
p = (Product)clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}

如何使用

public static void main(String[] args) {
Manager manager = new Manager();
UnderlinePen upen = new UnderlinePen('~');
MessageBox mbox = new MessageBox('*');
MessageBox sbox = new MessageBox('/'); manager.register("Strong Message", upen);
manager.register("Warning box", mbox);
manager.register("Slash box", sbox); Product p1 = manager.create("Strong Message");
p1.use("hello"); Product p2 = manager.create("Warning box");
p2.use("hello"); Product p3 = manager.create("Slash box");
p3.use("hello");
}
//结果
"hello"
~~~~~
*********
* hello *
*********
/////////
/ hello /
/////////

角色

Prototype(原型)

此角色负责定义用现有实例复制新实例的方法。对应于本例中的Product接口。

ConcretePrototype(具体的原型)

负责实现原型的方法。对应于本例中的MessageBox和UnderlinePen

Client(使用者)

负责使用原型的方法复制生成新的实例

模式的类图

我的理解

  说实话,由于经验所限,我不太能体会的到这个模式的好处。

  看看示例代码:代码实现的功能类似于一个文本编辑器,可以对文本进行下划线(UnderlinePen)和提示(MessageBox)两个操作。在一篇文章里面,可能有很多很多个下划线和提示操作。每一个都创建对象,创建过程简单还好,复杂的话那代码量就太恐怖了。所以搞一个原型对象,用到了就复制就行了。

  这只是我能理解的其中一个好处,更多内容可以看看这篇文章https://www.cnblogs.com/chenssy/p/3313339.html


另外原型模式涉及到了对象的深拷贝和浅拷贝。区别就在于:复制对象时,是否复制对象中的引用指向的内存。那篇文章里面有解释。

最新文章

  1. windows下搭建scrapywindows 7 (64) + python 3.5 (64)
  2. MEF入门之不求甚解,但力求简单能讲明白(二)
  3. 初步了解JSONP
  4. Java之重载与覆盖
  5. Linux下MySQL不能远程访问
  6. java web基础2HTTP协议知识点总结
  7. cmd扩展路径
  8. 可以binidng属性的属性【项目】
  9. 关于新的man版本出现“无法解析 /usr/share/man/zh_CN/man1/ls.1.gz: 没有那个文件或目录“
  10. OGG 单表初始化操作步骤
  11. C#.NET学习笔记7--11---算术运算符,变量赋值,变量的交换,布尔表达式1,布尔表达式2
  12. 前端 MVC 变形记
  13. 译者序(Core Data 应用开发实践指南)
  14. HTML5 使用 JS 生成二维码,带头像
  15. AVPass技术分析:银行劫持类病毒鼻祖BankBot再度来袭,如何绕过谷歌play的杀毒引擎?
  16. CSS使用position:sticky 实现粘性布局
  17. [APIO 2009] Atm
  18. Excel如何固定表头,任意一行
  19. 2018/03/11 每日一个Linux命令 之 top
  20. Golang之实现一个负载均衡算法(随机,轮询)

热门文章

  1. [Git] 013 远程仓库篇 第零话 使用前的一些配置
  2. SUST_ACM_2019届暑期ACM集训热身赛题解
  3. dfs(枚举)
  4. &lt;meta&gt;标签中http-equiv属性的属性值X-UA-Compatible详解
  5. python实现一个简单的网络聊天程序
  6. C# String的几种比较方法对比(Compare,CompareTo, CompareOrdinal、Equals)
  7. 03scikit-learn非监督学习
  8. alert(1) to win 12
  9. alert(1) to win 8
  10. 外媒:Apple面临着印度iPhone的停用