`
yangzhizhen
  • 浏览: 75295 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

原型模式简介

    博客分类:
  • Java
阅读更多

     这几天胡老师一直在讲关于设计模式的一些内容,自己也下去看了一些跟设计模式相关的书。根据自己的理解:所谓模式,就是一个模板,是经过前人总结的一个经验性的东西,而设计模式就是在设计方面的经验总结。现在大家普遍知道的是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)是软件设计模式中的一种结构型模式,它的主要目的是通过复制已有对象来创建新对象,从而减少创建新对象的成本。在原型模式中,类的实例化过程被替换为对已有实例的克隆操作,尤其适用...

    iOS设计模式之原型模式

    本文将深入探讨一种常见的设计模式——原型模式(Prototype Pattern),并结合具体的iOS应用场景进行解析。 原型模式是一种创建型设计模式,它的主要思想是通过复制已有对象来创建新对象,而不是通过构造函数来创建...

    设计模式之原型模式Java实现和类设计图

    原型模式(Prototype Pattern)是其中一种行为设计模式,主要用于对象创建。它通过复制已有对象来创建新对象,而不是通过传统的构造函数来创建。在Java中,原型模式可以有效地提高性能,特别是在创建复杂对象时。 #...

    android设计模式之原型模式

    本文将深入探讨Android设计模式中的“原型模式”(Prototype Pattern),并结合提供的"prototype"压缩包中的示例代码进行解析。 原型模式是一种创建型设计模式,它的主要思想是通过复制已有对象来创建新对象,而...

    经典设计模式讲解以及项目实战(Java版)

    为了更系统的学习设计模式,特地开了这样一个基于Java的设计模式【集中营】,都是笔者在实际工作中用到过或者学习过的一些设计模式的...Ibatis设计模式简介:主要是讲述Ibatis源码中运用到的一些设计模式(将来增加)

    23种JAVA设计模式和15种J2EE设计模式

    ##### 2.1 J2EE设计模式简介 J2EE设计模式主要关注于如何在J2EE环境中构建可伸缩、可维护的应用程序。这些模式有助于解决分布式计算环境下常见的问题,如远程调用、会话管理等。 **2.1.1 Session Façade—会话...

    设计模式——原型模式

    原型模式(Prototype Pattern)是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而无需知道具体创建过程的细节。这种模式的核心在于,它提供了一种对象克隆的简便方法,使得对象的创建过程对用户...

    设计模式简介

    创建型模式包括六种设计模式:简单工厂模式(SimpleFactory)、工厂方法模式(FactoryMethod)、抽象工厂模式(AbstractFactory)、创建者模式(Builder)、原型模式(Prototype)、单例模式(Singleton)。...

    设计模式专题之(五)原型模式---设计模式原型模式示例代码(python--c++)

    原型模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在原型模式中,一个对象可以被克隆以创建新对象,而无需知道具体的创建细节。这种模式在需要重复创建相似对象时非常有用,避免了每次创建新对象时都...

    设计模式 简介 经典

    设计模式是软件开发中的一种重要概念,它是经过实践验证、被广泛接受的代码设计解决方案的模板,旨在提高代码的可重用性、可读性和可维护性。设计模式的运用可以使开发者之间的沟通更加高效,同时也使得软件系统更加...

    二十种常见设计模式简介及JAVA实现代码.rar

    设计模式是软件工程中的一种最佳实践,它是在特定情境下为了解决常见问题而形成的一套可复用的解决方案模板。这些模式都是经过时间和实践验证的,能够提高代码的可读性、可维护性和可扩展性。以下是针对给定文件中的...

    设计模式迷你手册

    ### 设计模式简介 设计模式是在软件开发过程中解决常见问题的一种通用可重用的解决方案。它们代表了在特定情况下经过验证的最佳实践,并为常见的设计挑战提供了标准答案。设计模式不仅有助于提高代码的质量和可维护...

    Java扩大Java设计模式

    为了更系统的学习设计模式,特地开了这样一个基于Java的设计模式【集中营】,都是笔者在实际工作中用到过或者学习过的一些设计模式的一些提炼...4. Ibatis设计模式简介:主要是讲述Ibatis源码中运用到的一些设计模式

    深入浅出设计模式(英文扫描版)

    ### 设计模式简介 设计模式是在软件工程领域中,解决特定问题的一系列可复用的解决方案。它们代表了在某一类问题上,经过验证的最佳实践,能够帮助开发者避免常见的陷阱,并提供了一种通用的语言来描述代码结构,...

    基于Java实现的23种设计模式Demo,抽象工厂模式、建造模式、工厂方法模式、原型模式、单例模式、外观模式、适配器模式等

    基于Java实现的23种设计模式Demo,抽象工厂模式、建造模式、工厂方法模式、原型模式、单例模式、外观模式、适配器模式等 Java设计模式共有23种,分别为:抽象工厂模式、建造模式、工厂方法模式、原型模式、单例模式...

    Java 经典设计模式讲解以及项目实战

    设计模式简介:主要介绍各种设计模式的概念和运用场景等 设计模式综合运用:主要是笔者在实际工作中运用到的一些设计模式综合运用事例的提炼 Spring设计模式简介:主要是讲述Spring源码中运用到的一些设计模式 ...

Global site tag (gtag.js) - Google Analytics