这几天胡老师一直在讲关于设计模式的一些内容,自己也下去看了一些跟设计模式相关的书。根据自己的理解:所谓模式,就是一个模板,是经过前人总结的一个经验性的东西,而设计模式就是在设计方面的经验总结。现在大家普遍知道的是Gof总结出来的23种设计模式,这23种模式可以分为三个类别:创建型模式( 关于对象创建的模式)、结构型模式(关于对象的组成以及对象之间的依赖关系的模式)、行为型模式(关于对象行为的模式),这么多种设计模式有一个共同点,它们都是以对象为中心的,也就是以类为中心,这是值得注意的。如果按照一定的逻辑,比如说:按照对象的生命周期,从创建对象开始,再到对象之间的结构关系,最后到对象的使用,这样理解起来整体的框架就有了。
这里主要简单介绍一下关于创建对象过程中的原型模式(Prototype)。
为什么需要原型模式?
首先从具体事件上分析: 在画图工具里,要画圆只需要拖动工具条的画圆工具到绘图区即可,不需要从头开始一点一点地画一个圆,而且如果需要不同大小和颜色的圆,只需要复制一下,然后再修改它们的大小和颜色即可。
再从概念上进行分析: 比如有一个对象,在某一时刻该对象中已经包含了一个有效值,此时可能会需要一个和该对象完全相同的新对象,并且今后对新对象的任何改动都不会影响到原来对象中的值。也就是说,新对象和原来的对象是两个独立的对象,但新对象的初始值是由原来对象确定的。简单的说:就是要得到一个原有对象的拷贝。
什么是原型模式?
原型模式就是通过一个对象来表明要创建的对象类型,然后用复制这个原型对象的方法来创建更多的同类型对象。
原型模式的简单使用方法
①实现Cloneable接口
②复写java.lang.Object类的clone()方法
注意:
a.在Java中,通过赋值语句创建一个对象,则新对象和原来的对象是同一个引用。如果修改一个对象的值,另一个对象也会发生改变。这也是原型模式产生的一个重要原因。
b.Java中的所有类都默认继承java.lang.Object类,在Java.lang.Object类中有一个方法clone(),该方法返回一个Object对象的一个拷贝。
原型模式简单使用的代码示例
通过一个简单的钥匙的案例,来理解原型模式究竟怎么使用。
/**
* 钥匙的原型类
*/
public abstract class KeyPrototype implements Cloneable{
//钥匙长度
private float length;
//钥匙厚度
private float thick;
//钥匙颜色
private String color;
//复制对象
public Object clone(){
Object obj = null;
try {
obj = super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
//获取长度
public float getLength() {
return length;
}
//设置长度
public void setLength(float length) {
this.length = length;
}
//获取厚度
public float getThick() {
return thick;
}
//设置厚度
public void setThick(float thick) {
this.thick = thick;
}
//获取颜色
public String getColor() {
return color;
}
//设置颜色
public void setColor(String color) {
this.color = color;
}
}
/*
* 铜钥匙类
*/
public class CopperKey extends KeyPrototype {
/***
* 构造器
*/
public CopperKey(){
setColor("黄色");
}
}
/**
* 铝钥匙类
*/
public class AluminiumKey extends KeyPrototype{
/**
* 构造器
*/
public AluminiumKey(){
setColor("银色");
}
}
/**
* 客户端测试类
*/
public class Client {
/*
* 主方法
*/
public static void main(String[] args){
//创建一个铜钥匙类
KeyPrototype copperKey = new CopperKey();
//设置铜钥匙的长度
copperKey.setLength(3.1f);
//设置铜钥匙的厚度
copperKey.setThick(0.5f);
//克隆一把铜钥匙
KeyPrototype aluminiumKey = (KeyPrototype)copperKey.clone();
//设置克隆钥匙的颜色
aluminiumKey.setColor("银色");
System.out.println("第1次克隆后钥匙的颜色:"+copperKey.getColor()+" 长度:"+copperKey.getLength()+" 厚度:"+copperKey.getThick());
System.out.println("第1次克隆后钥匙的颜色:"+aluminiumKey.getColor()+" 长度:"+aluminiumKey.getLength()+" 厚度:"+aluminiumKey.getThick());
//创建一个铝钥匙
KeyPrototype aluminiumKey1 = new AluminiumKey();
//设置铝钥匙的长度
aluminiumKey1.setLength(4.0f);
//设置绿钥匙的厚度
aluminiumKey1.setThick(1.0f);
//克隆一把铝钥匙
KeyPrototype copperKey1 = (KeyPrototype)aluminiumKey1.clone();
//设置克隆钥匙的颜色
copperKey1.setColor("黄色");
System.out.println("第2次克隆前钥匙的颜色:"+aluminiumKey1.getColor()+" 长度:"+aluminiumKey1.getLength()+" 厚度:"+aluminiumKey1.getThick());
System.out.println("第2次克隆后钥匙的颜色:"+copperKey1.getColor()+" 长度:"+copperKey1.getLength()+" 厚度:"+copperKey1.getThick());
}
}
在Eclipse中输出结果是:
第1次克隆后钥匙的颜色:黄色 长度:3.1 厚度:0.5
第1次克隆后钥匙的颜色:银色 长度:3.1 厚度:0.5
第2次克隆前钥匙的颜色:银色 长度:4.0 厚度:1.0
第2次克隆后钥匙的颜色:黄色 长度:4.0 厚度:1.0
通过上面的结果,可以看出实现了复制对象的目的。下面再来看一个关于普通狗和克隆狗例子。
/*
* 狗类
*/
public class Dog {
//狗腿数
public int legCounts;
/**
* 构造器
*/
public Dog(int legCounts){
this.legCounts = legCounts;
}
/**
* 改变狗腿数目
*/
public void changeLegCounts(){
this.legCounts *= 2;
}
/**
* 将整型变量转换成字符串的方法
*/
public String toString(){
return Integer.toString(this.legCounts);
}
}
/**
* 实现了克隆接口的狗类
*/
public class DogClone implements Cloneable{
//狗腿数
public int legCounts;
//创建一个狗类,传入参数4
public Dog dog = new Dog(4);
/**
* 克隆的方法
*/
public Object clone(){
//定义一个DogClone对象
DogClone o = null;
try {
o = (DogClone)super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
/**
* 在客户端进行调用的类
*/
public class CloneMain {
/**
* 主方法
*/
public static void main(String[] args) {
//创建一个克隆狗对象
DogClone dogClone = new DogClone();
//设置克隆狗的狗腿数
dogClone.legCounts = 3;
System.out.println("原来的克隆狗腿数量:"+dogClone.legCounts);
System.out.println("原来的普通狗腿数量:"+dogClone.dog.legCounts);
//克隆一个克隆狗对象
DogClone dogClone1 = (DogClone)dogClone.clone();
//设置克隆的克隆狗腿数量
dogClone1.legCounts = 2;
//创建一个狗对象
Dog dog = dogClone1.dog;
//改变狗腿数量
dog.changeLegCounts();
System.out.println("克隆后原来的克隆狗腿数量:"+dogClone.legCounts);
System.out.println("克隆后原来的普通狗狗腿数量:"+dogClone.dog.legCounts);
System.out.println("克隆狗的克隆狗狗腿数量:"+dogClone1.legCounts);
System.out.println("克隆后的普通狗的狗腿数量:"+dogClone1.dog.legCounts);
}
}
在Eclipse中的输出结果是:
原来的克隆狗腿数量:3
原来的普通狗腿数量:4
克隆后原来的克隆狗腿数量:3
克隆后原来的普通狗狗腿数量:8
克隆狗的克隆狗狗腿数量:2
克隆后的普通狗的狗腿数量:8
可以看到:克隆后原来的普通狗的狗腿数目跟着克隆后的普通狗的狗腿数目变了,它们指向了同一对象。要解决这个问题,普通狗类也要实现Cloneable接口和复写clone()方法,这就是深度克隆。
用深度克隆实现的克隆狗类和普通狗类的测试
/*
* 狗类
*/
public class Dog implements Cloneable{
//狗腿数
public int legCounts;
/**
* 构造器
*/
public Dog(int legCounts){
this.legCounts = legCounts;
}
/**
* 改变狗腿数目
*/
public void changeLegCounts(){
this.legCounts *= 2;
}
/**
* 将整型变量转换成字符串的方法
*/
public String toString(){
return Integer.toString(this.legCounts);
}
/**
* Object提供的克隆方法
*/
public Object clone(){
//定义一个狗类对象
Dog o = null;
try {
o = (Dog)super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
/**
* 实现了克隆接口的狗类
*/
public class DogClone implements Cloneable{
//狗腿数
public int legCounts;
//创建一个狗类,传入参数4
public Dog dog = new Dog(4);
/**
* 克隆的方法
*/
public Object clone(){
//定义一个DogClone对象
DogClone o = null;
try {
o = (DogClone)super.clone();
} catch (Exception e) {
e.printStackTrace();
}
//克隆一个狗类对象
o.dog = (Dog)dog.clone();
return o;
}
}
/**
* 在客户端进行调用的类
*/
public class CloneMain {
/**
* 主方法
*/
public static void main(String[] args) {
//创建一个克隆狗对象
DogClone dogClone = new DogClone();
//设置克隆狗的狗腿数
dogClone.legCounts = 3;
System.out.println("原来的克隆狗腿数量:"+dogClone.legCounts);
System.out.println("原来的普通狗腿数量:"+dogClone.dog.legCounts);
//克隆一个克隆狗对象
DogClone dogClone1 = (DogClone)dogClone.clone();
//设置克隆的克隆狗腿数量
dogClone1.legCounts = 2;
//创建一个狗对象
Dog dog = dogClone1.dog;
//改变狗腿数量
dog.changeLegCounts();
System.out.println("克隆后原来的克隆狗腿数量:"+dogClone.legCounts);
System.out.println("克隆后原来的普通狗狗腿数量:"+dogClone.dog.legCounts);
System.out.println("克隆狗的克隆狗狗腿数量:"+dogClone1.legCounts);
System.out.println("克隆后的普通狗的狗腿数量:"+dogClone1.dog.legCounts);
}
}
在Eclipse中的运行结果是:
原来的克隆狗腿数量:3
原来的普通狗腿数量:4
克隆后原来的克隆狗腿数量:3
克隆后原来的普通狗狗腿数量:4
克隆狗的克隆狗狗腿数量:2
克隆后的普通狗的狗腿数量:8
这样就好了,克隆后原来的普通狗和克隆后的普通狗指向了不同的对象。
关于深度克隆的几点说明
①所谓的深度克隆是指让已实现Cloneable接口和复写clone()方法的类中的类对象的类也实现Cloneable接口并复写clone()方法。
②基本数据类型能够自动实现深度克隆。
③由于StringBuffer是一个finanl类,所以不能自动实现深度克隆。
原型模式的应用场景
当创建对象时,使用者不需要知道对象是如何创建的,只需要复制一个已有对象,然后在其上面进行修改以得到自己想要的对象,这个时候可以采用原型模式。
原型模式的优缺点
①优点:在原型模式中,可以动态地添加产品类,而且对整体结构没有影响。
②缺点:由于原型模式需要给每个类都配备一个克隆的方法,这就需要在设计时通盘考虑,因为在已有的类的基础上添加clone操作时比较困难的;而且实现深层次的复制时需要编写一定量的代码。
总之,一句话,要清楚原型模式什么时候用,怎么用,这才是最重要的。
分享到:
相关推荐
**原型模式(Prototype Pattern)**是软件设计模式中的结构型模式之一,主要用来简化实例化过程,减少类的创建。在原型模式中,一个对象可以被用作创建其他新对象的模板,通过复制已有对象来创建新对象,而不是通过new...
原型模式(Prototype Pattern)是软件设计模式中的一种结构型模式,它的主要目的是通过复制已有对象来创建新对象,从而减少创建新对象的成本。在原型模式中,类的实例化过程被替换为对已有实例的克隆操作,尤其适用...
原型模式(Prototype Pattern)是其中一种行为设计模式,主要用于对象创建。它通过复制已有对象来创建新对象,而不是通过传统的构造函数来创建。在Java中,原型模式可以有效地提高性能,特别是在创建复杂对象时。 #...
为了更系统的学习设计模式,特地开了这样一个基于Java的设计模式【集中营】,都是笔者在实际工作中用到过或者学习过的一些设计模式的...Ibatis设计模式简介:主要是讲述Ibatis源码中运用到的一些设计模式(将来增加)
原型模式(Prototype Pattern)是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而无需知道具体创建过程的细节。这种模式的核心在于,它提供了一种对象克隆的简便方法,使得对象的创建过程对用户...
创建型模式包括六种设计模式:简单工厂模式(SimpleFactory)、工厂方法模式(FactoryMethod)、抽象工厂模式(AbstractFactory)、创建者模式(Builder)、原型模式(Prototype)、单例模式(Singleton)。...
原型模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在原型模式中,一个对象可以被克隆以创建新对象,而无需知道具体的创建细节。这种模式在需要重复创建相似对象时非常有用,避免了每次创建新对象时都...
设计模式 的分类 总体来说设计模式分为三大类: 创建型模式(5): 工厂方法模式 、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式(7): 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、...
**原型设计模式(Prototype Pattern)**是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而不是通过构造函数来实例化新对象。在面向对象编程中,当我们需要频繁地创建具有相同或相似属性的对象时,...
### 设计模式简介 设计模式是在软件开发过程中解决常见问题的一种通用可重用的解决方案。它们代表了在特定情况下经过验证的最佳实践,并为常见的设计挑战提供了标准答案。设计模式不仅有助于提高代码的质量和可维护...
本篇文章将深入探讨“原型模式(Prototype)”这一经典的设计模式,它是面向对象设计的一个重要概念,尤其在C++编程中有着广泛的应用。 原型模式是一种创建型设计模式,它的核心思想是通过复制已有对象来创建新对象,...
### 设计模式简介 设计模式是在软件工程领域中,解决特定问题的一系列可复用的解决方案。它们代表了在某一类问题上,经过验证的最佳实践,能够帮助开发者避免常见的陷阱,并提供了一种通用的语言来描述代码结构,...
12.S8设计模式-1 设计模式简介 13.S8设计模式-2 创建型模式 14.S8设计模式-3 结构型模式 15.S8设计模式-4 行为型模式 16.5 设计模式总结 17.6 二叉树 18.7 算法进阶 2.s8算法1-2 汉诺塔+列表查找 3.s8算法1-3 排序...
【设计模式之原型模式】 设计模式是软件工程中的一种最佳实践,是对在特定上下文中反复出现的软件设计问题的解决方案。原型模式属于对象创建型模式,它的主要思想是通过复制已有对象来创建新对象,降低了类的实例化...
### Java设计模式之原型模式深度解析 #### 模式动机 在面向对象编程的世界里,对象的创建往往伴随着复杂的逻辑处理。特别是在某些场景下,对象的构造过程可能涉及大量资源的消耗,例如数据库连接、文件读写等。在...
ava常用设计模式-原型模式 原型模式(Prototype Pattern)是一种创建型设计模式,允许通过复制现有对象来创建新对象,而不是通过实例化类来创建新对象。在需要创建大量相似对象时非常有用,它可以避免重复创建对象...