设计模式之Prototype模式

通常我们会使用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);

    }
}
  • 控制台输出结果:

时间: 2024-08-30 03:42:41

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

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

写这些也许有人认为“为了模式而模式”.Insus.NET所想到的,每个大师成为大师之前,也许都得这样做. 走路,从小就开始学,直至现在,谁还不是为了走路而走路?一直重复着...... 很多人没有分享自己的经验,分享自己的过程,分享这东西,它不会因为分享而变少了...... 感动的故事,是因为分享了历程而让人感动...... 设计模式,在ASP.NET开发过程中,确实很多环境应用得到,也许只因为时间与效率问题,使用了最直接的方法来解决了.往往给以来的维护带来了繁杂变得难以进行. 进入主题,先看看这

Java 实现原型(Prototype)模式

public class BaseSpoon implements Cloneable {//spoon 匙, 调羹 String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected BaseSpoon clone() throws CloneNotSupportedException { System.o

菜鸟学设计模式系列笔记之Prototype模式(原型模式)

菜鸟学设计模式系列笔记之Prototype模式: Intent: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 Motivation:以一个已有的对象作为原型,通过它来创建新的对象. 在增加新的对象的时候,新对象的细节创建工作由自己来负责,从而使新对象的创建过程与框架隔离开来. 应用场景: (1)当一个系统应该独立于它的产品创建.构成和表示时 (2)当要实例化的类是在运行时刻指定时,例如动态加载 (3)为了避免创建一个产品类层次平行的工厂类层次时 (4)当一个类的实例只能有几个

java设计模式5--原型模式(Prototype)

本文地址:http://www.cnblogs.com/archimedes/p/java-prototype-pattern.html,转载请注明源地址. 原型模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 概述 原型模式是从一个对象出发得到一个和自己有相同状态的新对象的成熟模式,该模式的关键是将一个对象定义为原型,并为其提供复制自己的方法. java.lang.Object类的clone方法 参见<java中的深浅克隆> 适用性 1.当一个系统应该独立于它的产品创建

C++Prototype模式详解—设计模式(5)

关于这个模式,突然想到了小时候看的<西游记>,齐天大圣孙悟空再发飙的时候可以通过自己头上的3根毛立马复制出来成千上万的孙悟空,对付小妖怪很管用(数量最重要).Prototype模式也正是提供了自我复制的功能,就是说新对象的创建可以通过已有对象进行创建.在C++中拷贝构造函数(CopyConstructor)曾经是很多程序员的噩梦,浅层拷贝和深层拷贝的魔魇也是很多程序员在面试时候的快餐和系统崩溃时候的根源之一. 作用: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Proto

23种设计模式之原型模式(Prototype)

在系统开发过程中,有时候有些对象需要被频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后通过复制这个原型对象的办法,创建出更多同类型的对象.原型模式是一种对象创建型模式,用原型实例制定创建对象的种类,并且通过复制这些原型创建新的对象.原型模式又可分为两种:浅克隆和深克隆.浅克隆仅仅复制所考虑的对象,而不复制它所引用的对象,也就是其中的成员对象并不复制:深克隆除了对象本身被复制外,对象包含的引用也被复制,即成员对象也被复制. 优点: 1)可以在运行时添加或删除产品. 2)通过改

C#设计模式(6)——原型模式(Prototype Pattern)

一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象,然后如果采用工厂模式来创建这样的系统的话,随着产品类的不断增加,导致子类的数量不断增多,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适,然而原型模式可以很好地解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使

GOF设计模式——Prototype模式

一.什么是Prototype模式? 在编程中,我们可以使用new关键字指定类名来生成类的实例,但是有时候也会有不指定类名的前提下生成实例.因为有时候对象种类繁多,无法将它们整合到一个类中:或者,生成实例的过程过于复杂,难以根据类生成实例:又或者,想要将类与框架解耦.这时,为了能够在不使用类名的情况下生成实例,可以使用Prototype模式,Prototype模式又叫原型模式,专门做一些"复制"的操作. 二.Prototype模式思想 Client负责调用Prototype接口生成实例,

java设计模式--创建型模式

2016-04-24 10:10:34 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory)  这三种模式从上到下逐步抽象,并且更具一般性.GOF在<设计模式>一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory).将简单工厂模式