一、模式说明

  看了比较多的资料,对原型模式写的比较复杂,个人的理解就是模型复制,根据现有的类来直接创建新的类,而不是调用类的构造函数。

  那为什么不直接调用new方法来创建类的实例呢,主要一个原因是如果类的构造函数比较复杂,又需要大量的类实例对象,且这些类比较类似的时候,就可以使用原型模式,调用对象的克隆方法快读得到实例。另一个原因是,使用构造函数创建类时,语句MyClass myInstance = new MyClass();  这个Java语句中,我们使用了要创建的类的名字:MyClass,如此一来,就讲MyClass类和当前语句所在的类紧密耦合在一起了,而且,如果我们还不知道要创建的类的名字,但是想先定义类的创建方式,就需要使用原型模式。

二、原型模式的类图

三、原型模式中的角色

  • 原型(Protype)角色:负责定义复制现有实例生成新实例的方法
  • 具体原型(ConcretePrototype)角色:负责实现复制现有实例生成新实例的方法
  • 使用者(Client)角色:负责使用复制实例的方法生成新实例

四、代码示例

1.Product类:

package com.designpattern.cn.protptypepattern.patternframework;

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

  上面的Product类很简单,只是继承了java.lang.Clonable接口,该接口中并没有要求实现任何方法,这是一个标记接口,被该接口标记的类可以调用Clone方法来克隆类实例。需要注意的是,Clone方法并不是定义在Clonable接口中,而是定义在java.lang.Object中,另外需要提一点,Clone方法实现的是浅复制。

2.Manager类:

package com.designpattern.cn.protptypepattern.patternframework;

import java.util.HashMap;

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

  上面的Manager类提供了register方法,将字符串和Product接口注册保存到showcase中,现在还无法知道Product具体类是什么,但是可以确定这个具体类是实现了Product接口的,因此这个类可以调用use方法和createClone方法创建实例的克隆。

  接下来创建几种不同的Product具体的子类,每个子类都实现了Product接口:

3-1.MessageBox消息盒子类:

package com.designpattern.cn.protptypepattern.patterndemostrate;

import com.designpattern.cn.protptypepattern.patternframework.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;
}
}

3-2UnderlinePen类:

package com.designpattern.cn.protptypepattern.patterndemostrate;

import com.designpattern.cn.protptypepattern.patternframework.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 + 4; 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;
}
}

  从上面两个类可以看出,Manager类的create方法中并没有出现MessageBox和UnderlinePen这些字眼,取而代之使用的是自己定义的字符串,并将这个字符串注册到Manager类中,后续根据字符串来得到类实例(通过原型克隆得到)。如此一来,就将框架和具体的类名解耦开了。

4.测试类和运行结果:

原型模式在JavaScript中也有应用,后续再补充这方面的内容,可以对比看下Java和Javascript中实现原型模式的不同。

---------------------2019-06-27 00:13 比较晚了,今天加班到10点回家,原型模式还是比较重要的,这篇随笔后续继续补充-----------------------------

五、JavaScript中的原型模式

  在《Javascript 高级程序设计》一书中,在讲如何在Javascript中创建对象时,是这样介绍原型模式的:prototype是通过调用构造函数而创建的那个对象实例的原型对象。这句话反过来说:我们创建的每个函数都有一个prototype属性,它是一个指针,指向一个对象,这个对象包含了可以由特定类型的所有实例共享的属性和方法。总之:不必在构造函数中定义对象实例信息,而是将这些信息直接添加到原型对象中。

  举例说明:

  上面代码看出,当创建一个函数时(即使函数没有包含任何内容),就会创建一个prototype属性,该属性指向函数的原型对象,所有的原型对象会有一个constructor属性,该属性是一个指针,指向prototype属性所在的函数的指针。上面的例子:Person.prototype.constructor  指向 Person。

  使用原型对象的好处是:所有原型对象的实例都共享原型的属性和方法。换种说法,不必在构造函数中定义对象实例的信息,而是将这些对象信息放到原型对象中。

  由此我们可以想:如果我们自己创建一个对象,作为另一个对象的prototype属性值,然后通过Object.create(prototype, optionalDescriptorObjects)来实现原型继承。

  继续完善上面的代码:

  如果我们要自己实现原型模式:

六、与原型模式相关的模式

  • Flyweight享元模式:Prototype原型模式用于创建与当前实例完全相同的实例,Flyweight模式可以在不同的地方使用同一个实例
  • Memento备忘录模式:备忘录模式可以保存当前实例的状态,实现快照和撤销功能
  • Composite组合模式
  • Command命令模式:想要复制命令模式中的命令时,可以使用Protype模式。

一天一个设计模式——Prototype 原型模式的更多相关文章

  1. 设计模式:Prototype 原型模式 - 同学你抄过别人的作业么?-clone()方法的使用

    原型模式: 通过某个类的实例来创建对象 使用原型模式的好处: 好处是什么呢?当我们需要多次重复的创建一个类的示例的时候,我们可以使用new但是,new不仅仅耗费内存而且,如果new 某个类的构造方法中 ...

  2. C++设计模式-Prototype原型模式

    作用: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype模式提供了一个通过已存在对象进行新对象创建的接口(Clone), Clone()实现和具体的语言相关,在C+ ...

  3. 5.设计模式----prototype原型模式

    原型模式:做到是原型,那肯定是自己本身才是原型,原型模式属于对象的创建模式. 关于原型模式的实现方式分2种: (1)简单形式.(2)登记形式,这两种表现形式仅仅是原型模式的不同实现. package ...

  4. 设计模式_11_原型模式(prototype)深拷贝、浅拷贝

    设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...

  5. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  6. C#设计模式之六原型模式(Prototype)【创建型】

    一.引言 在开始今天的文章之前先说明一点,欢迎大家来指正.很多人说原型设计模式会节省机器内存,他们说是拷贝出来的对象,这些对象其实都是原型的复制,不会使用内存.我认为这是不对的,因为拷贝出来的每一个对 ...

  7. C#设计模式之五原型模式(Prototype Pattern)【创建型】

    一.引言 在开始今天的文章之前先说明一点,欢迎大家来指正.很多人说原型设计模式会节省机器内存,他们说是拷贝出来的对象,这些对象其实都是原型的复制,不会使用内存.我认为这是不对的,因为拷贝出来的每一个对 ...

  8. C#设计模式(6)——原型模式(Prototype Pattern) C# 深浅复制 MemberwiseClone

    C#设计模式(6)——原型模式(Prototype Pattern)   一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创 ...

  9. 设计模式05: Prototype 原型模式(创建型模式)

    Prototype 原型模式(创建型模式) 依赖关系的倒置抽象不应该依赖于实现细节,细节应该依赖于抽象.对所有的设计模式都是这样的. -抽象A直接依赖于实现细节b -抽象A依赖于抽象B,实现细节b依赖 ...

随机推荐

  1. Helm 架构【转】

    在实践之前,我们先来看看 Helm 的架构. Helm 有两个重要的概念:chart 和 release. chart 是创建一个应用的信息集合,包括各种 Kubernetes 对象的配置模板.参数定 ...

  2. java理解抽象类 2.19

    // Telphone.java public abstract class Telphone{ public abstract void call(); public abstract void m ...

  3. 嵊州普及Day2T1

    题意:对于给出的数列,有多少数可表示为另两数的和. 思路:先排个序,桶排思路.以一个数组储蓄所有出现的和.最后循环判断是否b[i]>0. 见代码: #include<iostream> ...

  4. OLTP和OLAP区别详解

    Oracle属于OLTP类型,而gp数据库属于OLAP类型的.具体了解如下: 数据库系统一般分为两种类型,一种是面向前台应用的,应用比较简单,但是重吞吐和高并发的OLTP类型:一种是重计算的,对大数据 ...

  5. Linux学习《第四章脚本》20200222

  6. Golang的标识符命名规则

    Golang的标识符命名规则 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.关键字 1>.Go语言有25个关键字 Go语言的25个关键字如下所示: break,defau ...

  7. mysql更新某一列数据

    UPDATE 表名 SET 字段名 = REPLACE(替换前的字段值, '替换前关键字', '替换后关键字'); select * from province; +----+------------ ...

  8. idea创建同名的maven工程时报错:Failed to create a Maven project 'xxx/pom.xml' already exists in VFS

    1.说明 原先有个 xxx 的 maven 工程,然后删掉了,又重新建了个同名的工程,而且目录也一样,结果报错: 可以在 Help ==> Show Log in Explorer 查看到以下具 ...

  9. JPA#复杂查询#引子

    _ 震惊....简历上写精通JPA的被下面几个问题震呆了.... 几个问题: 复杂查询如何从前端传递到后端,特别是多个条件的.且具有and和or等复杂逻辑,这个要如何封装呢? 多表查询? 自定义sql ...

  10. 七十六、SAP中数据库的查询用法之 COUNT(总数),SUM(求和),AVG(求平均),GROUP BY(分组)

    一.我们来查看一个sbook的数据库 二.查看这个表的内容如下 三.表数据如下 四.代码如下 五.结果如下 *&---------------------------------------- ...