通常我们会使用new 类名()的方法会去生成一个新的实例,但在开发过程中,有时候也会有“在不指定类名的前提下生成实例”的需求,那样,就只能根据现有实例来生成新的实例。

有三种情况,不能根据类来生成实例:

  1. 对象种类繁多,无法将它们整合到一个类中时;
  2. 难以根据类生成实例的时;
  3. 想解耦框架与生成的实例时。

不根据类来生成实例,而是根据实例来生成实例,就是Prototype模式,又叫原型模式。

实例程序是将字符串放入方框中或者加上下划线显示:

  • Product接口
package site.wangxin520.gof.prototype.framework;

/**
* 所有的需要new出来的对象全部需要实现Product接口
* Product接口中,继承了Cloneable接口,方便子类调用clone()方法去复制本身对象
* Product接口中,声明了use(String s)和createClone()抽象方法,具体实现通过子类进行
* @author wangXgnaw
*
*/
public interface Product extends Cloneable{
/**
* 修饰字符串
* @param s 被修饰的字符串
*/
public void use(String s);
/**
* 复制(克隆)一个对象出来
* @return Product 返回一个新对象,这个返回的对象并不是通过new出来的
*/
public Product createClone();
}
  • Manager类
package site.wangxin520.gof.prototype.framework;

import java.util.HashMap;

import org.springframework.beans.factory.annotation.Autowired;

/**
* 使用Product接口来复制实例
* 采用HashMap集合,来保存/注册对象
* 这里是模仿了Spring源码中的注册和创建bean的方法
* @author wangXgnaw
*
*/
@SuppressWarnings("all")
public class Manager { /**
* 注册对象用
*/
private HashMap showcase=new HashMap();
/**
* 注册对象,模仿了Spring源码中的注册
* @param name 对象名,在spring源码中可以使用alian别名和beanname名
* @param product 实例化的对象,这里是注册一个原型对象,方便后面调用的时候克隆/复制出新对象
*/
public void register(String name,Product product){
showcase.put(name, product);
}
/**
* 重头戏
* 根据传入的名字,获取到对象
* 这里注意的是“返回对象”标注的那边,使用的是createclone()方法,来复制一个新实例。
* @param protoname 需要实例化的对象名
* @return Product 返回一个实现了Product接口的对象
*/
public Product create(String protoname){
Product product=(Product) showcase.get(protoname);
//返回对象
return product.createClone();
} }
  • UnderlinePen类
package site.wangxin520.gof.prototype;

import site.wangxin520.gof.prototype.framework.Product;

/**
* 显示一个下划线,具体不做赘述,同MessageBox
* @author wangXgnaw
*
*/
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.print(" ");
for (int i = 0; i < length; i++) {
System.out.print(ulchar);
}
System.out.println("");
} public Product createClone(){
Product product=null;
try {
product = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return product;
} }
  • MessageBox类
package site.wangxin520.gof.prototype;

import site.wangxin520.gof.prototype.framework.Product;

/**
* 显示消息框,实现了Product接口
* @author wangXgnaw
* 逻辑不做过多赘述
*/
public class MessageBox implements Product{ private char decochar;
public MessageBox(char decochar){
this.decochar=decochar;
}
public void use(String s){
int lenght=s.getBytes().length;
for (int i = 0; i < lenght+4; i++) {
System.out.print(decochar);
}
System.out.println("");
System.out.println(decochar+" "+s+" "+decochar);
for (int i = 0; i < lenght+4; i++) {
System.out.print(decochar);
}
System.out.println("");
} /*
* 创建一个克隆对象,由于继承了cloneable接口,所以采用的是clone()方法,直接克隆出自己本身出来
* @see site.wangxin520.gof.prototype.framework.Product#createClone()
*/
public Product createClone(){
Product product=null;
try {
product = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return product;
}
}
  • Prototype测试类
package site.wangxin520.gof.prototype;

import site.wangxin520.gof.prototype.framework.Manager;
import site.wangxin520.gof.prototype.framework.Product; /**
* ProtoType模式的测试类
* @author wangXgnaw
*
*/
public class PrototypeTest {
public static void main(String[] args) { //新建一个manager管理者,用于管理注册的bean,同Spring中一样
Manager manager=new Manager();
//先初始化一个类
UnderlinePen ulpen=new UnderlinePen('~');
MessageBox mbox1=new MessageBox('*');
MessageBox mbox2=new MessageBox('/');
//把初始化的类进行注册
manager.register("strong message", ulpen);
manager.register("warning box", mbox1);
manager.register("slash box", mbox2); /**
* 以上的方法,实现了spring框架中的注册容器的概念,可通过配置文件进行
* 下面就是使用这个容器来为我们做事
*/ //通过manager去创建一个新的product
Product p1 = manager.create("strong message");
p1.use("hello word");
//为了方便观察,使用了一个地址值相同判断,看与之前初始化对象是否是一样的,后同
System.out.println(p1==ulpen); Product p2 = manager.create("warning box");
p2.use("hello word");
System.out.println(p2==mbox1);
Product p3 = manager.create("slash box");
p3.use("hello word");
System.out.println(p3==mbox2); }
}
  • 控制台输出结果:

设计模式之Prototype模式的更多相关文章

  1. 设计模式--原型(Prototype)模式

    写这些也许有人认为“为了模式而模式”.Insus.NET所想到的,每个大师成为大师之前,也许都得这样做. 走路,从小就开始学,直至现在,谁还不是为了走路而走路?一直重复着...... 很多人没有分享自 ...

  2. 设计模式:prototype模式

    使用场景:在不能根据类创建对象的时候,根据已有的对象创建对象 不能根据类创建对象的情况: 创建一个类的对象时,需要根据多种对象来创建,创建的过程非常复杂 难以根据类生成对象 例子: class Pro ...

  3. swift设计模式学习 - 原型模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 原型模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 定义 用原型实例指定创建对象的种类,并且通 ...

  4. Java 实现原型(Prototype)模式

    public class BaseSpoon implements Cloneable {//spoon 匙, 调羹 String name; public String getName() { re ...

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

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

  6. [设计模式] 4 原型模式 prototype

    设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...

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

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

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

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

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

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

随机推荐

  1. iOS开发总结-Xcode常见错误

    iOS开发总结-Xcode常见错误 "file/file.h"filenotfound 如果遇到这种类型的问题报错,可以分为三部来解决,由简到复杂一步一步来,直到解决问题位置. 1 ...

  2. ng-class中的if else判断

    ng-class中的if else判断 来自于stackoverflow的一个问题,自己刚好用到,搬过来做个标记.原问题链接 在使用ng-class时,有些时候会碰到根据是否满足条件来设置元素的样式, ...

  3. Hadoop单机Hadoop测试环境搭建

    Hadoop单机Hadoop测试环境搭建: 1. 安装jdk,并配置环境变量,配置ssh免密码登录 2. 下载安装包hadoop-2.7.3.tar.gz 3. 配置/etc/hosts 127.0. ...

  4. python保存爬取的图片

    用爬虫抓取图片的保存 保存图片 request=urllib2.Request(randNumberUrl,data,headers) picture=opener.open(request).rea ...

  5. 扩展RBAC用户角色权限设计方案<转>

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...

  6. 虚拟化–操作系统级 LXC Linux Containers内核轻量级虚拟化技术

    友情提示:非原文链接可能会影响您的阅读体验,欢迎查看原文.(http://blog.geekcome.com) 原文地址:http://blog.geekcome.com/archives/288 软 ...

  7. nodejs入门开发与常用模块

    npm:NodeJs包管理器 express:服务器端比较流行的MVC框架,处理服务请求,路由转发,逻辑处理 http://socket.io:实现服务端和客户端socket通信解决方案 ); // ...

  8. Vim快捷键操作命令大全

        Vim是一个超牛的编辑器,命令功能十分强大 .而且这些命令大都可以进行组合 ,比如,9yy命令表示复制9行内容,9表示要复制的行数,同样100dd表示删除100行,当数字和命令合作的时候,就比 ...

  9. cmake 安装 mysql5.5 版本

    1.安装确保以下系统相关库文件 gcc gcc-c++ autoconf automake zlib* libxml* ncurses-devel libmcrypt* libtool*(libtoo ...

  10. IoC是一个很大的概念,可以用不同的方式实现。其主要形式有两种:

    IoC是一个很大的概念,可以用不同的方式实现.其主要形式有两种: ◇依赖查找:容器提供回调接口和上下文条件给组件.EJB和ApacheAvalon都使用这种方式.这样一来,组件就必须使用容器提供的AP ...