创建型设计-原型模式

来源:互联网 发布:nginx header安全配置 编辑:程序博客网 时间:2024/05/22 01:50

           声明一下:本文的文字多数文字都是来自网上,只有例子是自己写的。因为自我感觉还没有能力能够系统的解释一个模式,已经有现成的比较完善的说明,就不重复造轮子哈。


        原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的。
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据。

适用场景
        在以下情况下可以考虑使用原型模式:
(1) 创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。
(2) 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占用内存较少时,可以使用原型模式配合备忘录模式来实现。
(3) 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。

原型类图:

例子

浅复制:

prototype:

public class CopyValidater implements Cloneable  {    private Validater validater;    public Validater getValidater() {        return validater;    }    public void setValidater(Validater validater) {        this.validater = validater;    }    public CopyValidater cloneable(){        CopyValidater conValidater=new CopyValidater();        try {            conValidater=(CopyValidater) super.clone();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return conValidater;    }}


ConcretePrototype:

public class Validater {    private String fieldName;    private String operater;    private Object data;    private int dataType;    public String getFieldName() {        return fieldName;    }    public void setFieldName(String fieldName) {        this.fieldName = fieldName;    }    public String getOperater() {        return operater;    }    public void setOperater(String operater) {        this.operater = operater;    }    public Object getData() {        return data;    }    public void setData(Object data) {        this.data = data;    }    public int getDataType() {        return dataType;    }    public void setDataType(int dataType) {        this.dataType = dataType;    }    @Override    public String toString() {        return "Validater{" +                "fieldName='" + fieldName + '\'' +                ", operater='" + operater + '\'' +                ", data=" + data +                ", dataType='" + dataType + '\'' +                '}';    }}

Client:

public class Main {    public static void main(String[] args) {        Validater vadata=new Validater();        vadata.setData("1");        vadata.setDataType(1);        vadata.setFieldName("validater");        vadata.setOperater("notcopy");        CopyValidater notcopy=new CopyValidater();        notcopy.setValidater(vadata);        CopyValidater copy=notcopy.cloneable(); //克隆后的对象        System.out.println("notcopy:"+notcopy.getValidater().toString());        System.out.println("copy:"+copy.getValidater().toString());        System.out.println("======================================修改后============================================");        /*************** 修改克隆后的对象**********************/        //修改克隆对象的属性值        copy.getValidater().setData("2");        copy.getValidater().setOperater("copyValidater");        copy.getValidater().setDataType(2);        System.out.println("notcopy:"+notcopy.getValidater().toString());        System.out.println("copy:"+copy.getValidater().toString());    }}
结果集:

notcopy:Validater{fieldName='validater', operater='notcopy', data=1, dataType='1'}
copy:Validater{fieldName='validater', operater='notcopy', data=1, dataType='1'}
======================================修改后==============================================
notcopy:Validater{fieldName='validater', operater='copyValidater', data=2, dataType='2'}
copy:Validater{fieldName='validater', operater='copyValidater', data=2, dataType='2'}


深复制:
prototype:

public class CopyValidater implements Cloneable  {    private Validater validater;    public Validater getValidater() {        return validater;    }    public void setValidater(Validater validater) {        this.validater = validater;    }    public CopyValidater cloneable(){        CopyValidater conValidater=new CopyValidater();        try {            conValidater=(CopyValidater) super.clone(); //拷贝当前对象            conValidater.validater=(Validater)this.validater.cloneable();//拷贝对象的属性        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return conValidater;    }}
ConcretePrototype:
public class Validater implements Cloneable {    private String fieldName;    private String operater;    private Object data;    private int dataType;    public String getFieldName() {        return fieldName;    }    public void setFieldName(String fieldName) {        this.fieldName = fieldName;    }    public String getOperater() {        return operater;    }    public void setOperater(String operater) {        this.operater = operater;    }    public Object getData() {        return data;    }    public void setData(Object data) {        this.data = data;    }    public int getDataType() {        return dataType;    }    public void setDataType(int dataType) {        this.dataType = dataType;    }    public Validater cloneable(){        Validater validater=null;        try {            validater=(Validater)super.clone();        } catch (Throwable e) {            e.printStackTrace();        }        return validater;    }    @Override    public String toString() {        return "Validater{" +                "fieldName='" + fieldName + '\'' +                ", operater='" + operater + '\'' +                ", data=" + data +                ", dataType='" + dataType + '\'' +                '}';    }}
client:(与浅复制代码相同)

public class Main {    public static void main(String[] args) {        Validater vadata=new Validater();        vadata.setData("1");        vadata.setDataType(1);        vadata.setFieldName("validater");        vadata.setOperater("notcopy");        CopyValidater notcopy=new CopyValidater();        notcopy.setValidater(vadata);        CopyValidater copy=notcopy.cloneable(); //克隆后的对象        System.out.println("notcopy:"+notcopy.getValidater().toString());        System.out.println("copy:"+copy.getValidater().toString());        System.out.println("======================================修改后=============================================");        /*************** 修改克隆后的对象**********************/        //修改克隆对象的属性值        copy.getValidater().setData("2");        copy.getValidater().setOperater("copyValidater");        copy.getValidater().setDataType(2);        System.out.println("notcopy:"+notcopy.getValidater().toString());        System.out.println("copy:"+copy.getValidater().toString());    }}
结果集:

notcopy:Validater{fieldName='validater', operater='notcopy', data=1, dataType='1'}
copy:Validater{fieldName='validater', operater='notcopy', data=1, dataType='1'}
======================================修改后==============================================
notcopy:Validater{fieldName='validater', operater='notcopy', data=1, dataType='1'}
copy:Validater{fieldName='validater', operater='copyValidater', data=2, dataType='2'}


根据深浅复制代码,我们可以得出:

浅复制: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
复制: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.

 原型模式作为一种快速创建大量相同或相似对象的方式,在软件开发中应用较为广泛,很多软件提供的复制(Ctrl + C)和粘贴(Ctrl + V)操作就是原型模式的典型应用,下面对该模式的使用效果和适用情况进行简单的总结。
1.优点
(1) 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
(2) 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。
(3) 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品。
(4) 可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。
2.缺点
      原型模式的主要缺点如下:
(1) 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。
(2) 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。



阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 王者荣耀战队活跃度满了怎么办 win10你的账户已被停用怎么办 电脑一键还原后一直黑屏怎么办? 被打了狂犬疫苗的狗咬伤怎么办 美版苹果7系统坏了怎么办 韩服的球球大作战网络不稳定怎么办 球球大作战号删了找不回来怎么办 队友传足球球的时候接不到怎么办 魅族手机中病毒锁机了怎么办? vbs打开是和文本文档一样怎么办 把电脑注册表删了电脑动不了怎么办 注册表删一项后电脑启动不了怎么办 解压过的过的软件安装包损坏怎么办 手机中病毒自动发短信扣费怎么办 苹果手机中的高德地图打不开怎么办 大晚上挂了别人的车怎么办 手机不兼容高版本微信怎么办 绝地求生右下角小地图变大了怎么办 杯孕当月做了C丁怎么办 玩全军出击手机发烫就出现卡怎么办 不小心买了彩虹六号肝帝版本怎么办 微信游戏刺激战场电脑卡怎么办 电脑更新了以前的东西都没了怎么办 安装黑苹果鼠标键盘不能用怎么办 苹果开机卡在白底黑苹果怎么办 信长之野望14没有剧情触发怎么办 玩cf手游手机屏幕摩擦力大怎么办 网吧有战地1没有橘子平台怎么办 俩人打仗了对方想讹我怎么办 环世界模组装多了打不开怎么办 手机百度云视频播放画面太小怎么办 ps文件说数据似乎已经损坏怎么办 百度云中的压缩包下载的很慢怎么办 游戏压缩出现未知错误或损坏怎么办 百度云里的压缩包解压后损坏怎么办 联创打印时显示压缩文件失败怎么办 电脑的软件打开出现未知格式怎么办 图片只突出人物边上全黑怎么办 合金机兵存档密码忘了怎么办 手机网页验证码无法加载插件怎么办 绝地求生次激战场机型不支持怎么办