23种设计模式(六) —— 手写实现 Prototype 模式 (生成实例)

六、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. 难以根据类生成实例。

  3. 解耦框架与生成的实例时。

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 模式中登场的角色-

====================================================================================

  • 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)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你需要这些资料,⬅专栏获取

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值