`

原型模式(Prototype)解析例子

阅读更多
    http://tianli.blog.51cto.com/190322/40705
摘要:本文深入浅出的讲述了设计模式中的原型模式,并给出了简单的示例,例子浅显易懂,并附带源代码。
       原型模式属于创建型模式,其意图是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。这就要求可以通过复制的方法复制一个对象。定制一个通用的图形编辑器框架,编辑器框架可能有一个工具选择板用以将这些图形对象添加到画布上,这个选择板还可能包括选择,移动,和其他操纵音乐对象的工具。用户可以点击选择板上的按钮来画一个图形,或者用户可以选择一个图形移动。这里的关键是定义一个抽象的类,每个选择板上的图形都实现此类的抽象方法,如:选择板上有一个画矩形图形的按钮,当选择这个按钮在画布上点击时,便画出一个图形。解决办法是通过克隆一个矩形的实例来创建新的图形,被克隆的矩形就是原型模式的原型。画出来的矩形通过调整大小参数,移动位置最终达到用户的需求。
  
适用性:
       当一个系统应该独立于他的产品创建,构成和表示时,要使用Prototype模式,以及
当要实例化的类是在运行时刻指定的,或者为了避免创建一个与产品类层次平行的工厂类层次时,或者当一个类的实例只能有几个不同状态组合的一种时。建立相应数目的原型并克隆他们可能比每次用合适的状态手工实例化该类更方便一些。

例如:有一个画板(toolbar)可以从中取到两种图形:圆型(circle)和矩形(rectangle)它们都属于原型(Prototype),当客户需要画一个图形时便从画板中去一个图形,原型模式的关键就在于画板克隆一个图形对象,然后返回给客户。
                 图1原型模式的UML图
参与者:
    Prototype:声明一个克隆自身的接口。
    ConcretePrototye(Circle):实现一个克隆自身的操作。
    Client:让一个原型克隆自身从而创建一个新的对象。
使用Prototype有以下的效果:
l         运行时刻增加和删除产品,原型模式允许只通过客户注册原型实例就可以将一个新的具体产品并入系统,
l         改变值以指定新对象 高度动态的系统允许你通过对象复合定义新的行为。
l         改变结构以指定新对象 许多应用由部件和子部件来创建对象,这样的应用通常允许你实例化复杂的,用户定义的结构。
l         减少子类的构造
l         用类动态配置应用 一些运行时刻环境允许你动态将类类装载到应用中。
Prototype的主要缺陷是每一个Prototype的子类都必须实现Clone操作,这可能困难,当内部包括一个不支持拷贝或者有循环引用的对象时,实现克隆可能也会困难。
具体代码:
Prototype代码:
package prototype;
public interface Prototype extends Cloneable{
    public Object clone();
    public String getName();
}
Rectangle代码:
package prototype;
public class Rectangle implements Prototype,Command{
    public Object clone(){
       Object clone=null;
       try{
           clone=super.clone();
       }catch(CloneNotSupportedException e){
           System.err.println("Clone not supported!");
       }
       return clone;
    }
    public String getName(){
       return "Rectangle";
    }
    public void draw(){
       System.out.println("Draw a rectangle");
    }
}
Circle代码:
package prototype;
public class Circle implements Prototype,Command{
    public Object clone(){
       Object clone=null;
       try{
           clone=super.clone();
       }catch(CloneNotSupportedException e){
           System.err.println("Colone not support!");
       }
       return clone;
    }
    public String getName(){
       return "circle";
    }
    public void draw(){
       System.out.println("Draw a circle");
    }
}
Command代码;
package prototype;
public interface Command{
    public void draw();
}
Toolbar代码:
package prototype;
import java.util.HashMap;
public class Toolbar{
    private HashMap tools=null;
    public Toolbar(){
       tools = new HashMap();
       tools.put("circle",new Circle());
       tools.put("rectangle",new Rectangle());     
    }
    public Object getClone(String key){
       Object obj = tools.get(key);
       if(obj!=null)return ((Prototype)obj).clone();
       return null;
    }
}
Client代码:
package prototype;
public class Client{
    public static void main(String[] args){
       Toolbar tb = new Toolbar();
       Command c=(Command)tb.getClone("circle");
        c.draw();
       c=(Command)tb.getClone("rectangle");
       c.draw();
     
    }
}
总结:原型模式在生成复杂对象比较苦难的环境中比较适用,通过克隆已有对象来实现创建新的对象,节省了时间和空间。
本文出自 “凌辉” 博客,请务必保留此出处http://tianli.blog.51cto.com/190322/40705
分享到:
评论

相关推荐

    戏说JS中的原型-Prototype

    什么是原型:在了解原型链之前我们先来看看一个函数在创建过程中做了哪些事情,举一个空函数的例子:当我们在代码里面声明这么一个空函数,js解析的本质是:1、创建一个对象(有constructor属性及[[Prototype]]属性...

    js原型链与继承解析(初体验)

    然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享其属性(下面的两个例子会详细介绍)。 function foo(){}...

    JavaScript中原型链存在的问题解析

    我们知道使用原型链实现继承是一个goodway:)看个原型链继承的例子。 function A () { this.abc = 44; } A.prototype.getAbc = function (){ return this.abc; }; function B() { } B.prototype = new A(); // B...

    JavaScript原型和继承

    前几天看了《再谈js面向对象编程》,当时就请教...当我们在代码里面声明这么一个空函数,js解析的本质是(肤浅理解有待深入):1、创建一个对象(有constructor属性及[[Prototype]]属性),根据ECMA,其中[[Prototype]

    asp.net知识库

    一个XSLT的简单例子 XSLXSLT板主题整理 xsl入门的好文章 新手学习XSL的好东西 XSL语法介绍 XSL学习心得 - 调用属性值 XSLT与XML转换的详细介绍 功能应用 读写搜索 基础教程 RSS Web2.0时代,RSS你会用了吗?(技术...

    PPScan:客户端原型污染扫描仪

    例子为什么选择窗口模式?当应用程序使用帧清除时,窗口模式很有用。例子笔记如果看到XFO或CSP错误,请重新加载扩展。扩展程序在chrome 86版上进行了测试。找到PP了吗?下一步是什么?在这里检查小工具

    Javascript组合继承方法代码实例解析

    组合继承,指将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后思路使用用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承。这样,即通过在原型上定义方法...

    正则表达式

    尾部的数字,那么如果我们将模式的数字部分放在括号中 (/ [a-z] + (\d+)/) ,我们就可以从所检索到的任何匹配中抽取数字了,之后我们会对此进行解析的. 代括号的子表达式的另一个用途是,允许我们在同一正则表达式的...

    Spring 2.0 开发参考手册

    3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.4. 自定义作用域 3.5. 定制bean特性 3.5.1. Lifecycle接口 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean ...

    spring chm文档

    3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.4. 自定义作用域 3.5. 定制bean特性 3.5.1. Lifecycle接口 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean ...

    Spring中文帮助文档

    11.1.1. 选择一种工作模式 11.1.2. Spring JDBC包结构 11.2. 利用JDBC核心类控制JDBC的基本操作和错误处理 11.2.1. JdbcTemplate类 11.2.2. NamedParameterJdbcTemplate类 11.2.3. SimpleJdbcTemplate类 ...

    Spring API

    11.1.1. 选择一种工作模式 11.1.2. Spring JDBC包结构 11.2. 利用JDBC核心类控制JDBC的基本操作和错误处理 11.2.1. JdbcTemplate类 11.2.2. NamedParameterJdbcTemplate类 11.2.3. SimpleJdbcTemplate类 ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.3.1. 初始化web配置 3.4.3.2. Request作用域 3.4.3.3. Session作用域 3.4.3.4. global session作用域 3.4.3.5. 作用域bean与依赖 3.4.4. 自定义作用域 3.5. 定制bean...

Global site tag (gtag.js) - Google Analytics