六、Prototype 模式
-
一、通过复制生成的实例
-
-
- 1.1 以下情况不根据类来生成实例
-
-
1.2 如何实现不依赖类来生成实例?
-
二、示例程序
-
-
- 2.1 实现目标
-
-
2.2 类和接口一览表
-
2.3 代码实现
-
三、Prototype 模式中登场的角色-
-
四、补充
-
-
- 4.1 相关设计模式
-
-
4.2 clone 方法 和 java.lang.Cloneable 接口
-
4.3 clone() 方法在哪里定义的?
-
五、源代码以及原文档
Author:Gorit
Date:2021/1/13
Refer:《图解设计模式》
2021年发表博文: 15/50
==========================================================================
在 java 中,我们可以通过 new 关键字来生成实例。我们通常这样生成的实例都是要指定类名的。
但是有时候,我们在开放的过程中,也有不指定类名来生成实例的需求。
1.1 以下情况不根据类来生成实例
在以下情况中,我们不能根据类来生成实例,而要根据已有的实例来生成新的实例。
-
对象种类繁多,无法将他们整合到一个类中。
-
难以根据类生成实例。
-
解耦框架与生成的实例时。
1.2 如何实现不依赖类来生成实例?
不根据类来生成实例,而是根据实例来生成实例的设计模式叫 Prototype 模式
Prototype 有原型,**模型 **的意思。在设计模式中,它是根据实例原型,实例模型来生成新的实例。
现在来回答标题提出的问题:
我们可以通过 clone 创建出实例的副本。我们还会用刀拍 clone 方法与 Cloneable 接口的使用方法。
=====================================================================
2.1 实现目标
我们要实现的程序功能是:将字符串放入方框,显示出来 或者 加上下划线显示出来
2.2 类和接口一览表
| 包 | 名字 | 说明 |
| — | — | — |
| framework | Product | 声明了抽象方法 use 和 createClone 接口 |
| framework | Manager | 调用 createClone 方法复制实例类 |
| 无 | MessageBox | 将字符串放入方框,并显示出来,实现 use 方法 和 createClone 方法 |
| 无 | UnderlinePen | 给字符串加上上下划线并显示出来的类,实现了 use 和 createClone 方法 |
| 无 | Main | 测试程序行为的类 |
Product 接口和 Message 类属于 framework包,负责复制实例。
Manager 类虽然会调用 createClone 方法,但是对于具体要复制哪个。并不知道。
但是只要实现了 Product 接口的类,调用它的 createClone 方法就可以复制出新的实例。
MessageBox 类 和 UnderlinePen 类是两个实现了 Product 接口的类。只用实现将这两个类“注册”到 Manager 类中,就可以随时复制新的实例。
2.3 代码实现
Product
package Prototype.framework;
// 继承复制的接口, Cloneable 通过调用 clone 实现对象的调用
public interface Product extends Cloneable{
public abstract void use(String s); // 具体是如何使用,交给子类去实现
public abstract Product createClone();
}
Manager
package Prototype.framework;
import java.util.*;
/**
- 使用 product 接口复制实例
*/
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();
}
}
MessageBox
package Prototype;
import Prototype.framework.Product;
public class MessageBox implements Product {
private char decochar;
public MessageBox(char decochar) {
this.decochar = decochar;
}
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(“”);
}
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
UnderlinePen
package Prototype;
import Prototype.framework.Product;
public class UnderlinePen implements Product {
private char ulchar;
public UnderlinePen(char ulchar) {
this.ulchar = ulchar;
}
public void use(String s) {
int length = s.getBytes().length;
System.out.println(“”" + s + “”");
System.out.println(" ");
for (int i=0;i< length;i++) {
System.out.print(ulchar);
}
System.out.println(“”);
}
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
Main
package Prototype;
import Prototype.framework.Manager;
import Prototype.framework.Product;
public class Main {
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 msg”,upen);
manager.register(“warning box”,mbox);
manager.register(“slash box”,sbox);
// 生成
Product p1 = manager.create(“strong msg”);
p1.use(“Hello World”);
Product p2 = manager.create(“warning box”);
p2.use(“Hello World”);
Product p3 = manager.create(“slash box”);
p3.use(“Hello World”);
}
}
执行效果
====================================================================================
- Prototype(原型)
Product 角色负责定义用于复制现有实例来生成新实例的方法。 Product 接口扮演此角色
- ConcretePrototupe(具体的原型)
ConcretePrototype 角色负责实现复制现有的实例并生成新实例的方法。在上述程序中, MessageBox类 和 UnderlinePen 类扮演此角色
- Client (使用者)
Client 角色负责使用复制实例的方法生成新的实例。在示例中,由 Message类 扮演此角色。
===================================================================
4.1 相关设计模式
-
Flyweight 模式(可以在不同地方使用同一个实例)
-
Memento 模式(可以保存当前实例状态,以实现快照和撤销功能)
-
Composite 模式 以及 Decorator 模式(动态创建复杂结构的实例,这里可以用 Prototype 模式快速生成实例)
-
Command 模式(该模式中出现的命令需要复制的时候,可以使用 Prototype)
4.2 clone 方法 和 java.lang.Cloneable 接口
要使用 clone 方法进行复制实例,就要实现 Cloneable 接口,否则就会出现 CloneNotSupportedException
java.lang 包是默认引入的。因此不必显示引入 java.lang 包调用 clone() 方法
4.3 clone() 方法在哪里定义的?
clone() 方法定义在 java.lang.Object 中,因为 Object 类是所有 java 类的父类。因此所有类都默认继承了 Object 类。
五、源代码以及原文档
最后
小编这些年深知大多数初中级工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Java全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你需要这些资料,⬅专栏获取
类都默认继承了 Object 类。
五、源代码以及原文档
最后
小编这些年深知大多数初中级工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Java全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-0NIjtEik-1719503294402)]
[外链图片转存中…(img-9lwcfR4m-1719503294403)]
[外链图片转存中…(img-ywckawYE-1719503294403)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你需要这些资料,⬅专栏获取