`

原型设计模式prototype

阅读更多
基于《研磨设计模式》,没什么实质突破,简单的记录一下
问题引人:考虑一个订单系统。该系统里有一个保存订单的业务功能,在这个功能里,用户有这样的需求当订单的预定产品数量超过1000的时候,就需要把订单拆成两份订单来保存,如果拆分后还是超过1000,继续拆分,直到每份订单的预定产品数量不超过1000。
一个订单,有个人订单和公司订单。不管什么类型的订单,都要能正常的处理,如何实现???不用模式的解决方案见notusingMode包,该解决方案的订单业务处理对象
必须知道订单 的具体实现类,才能进行处理,也难以扩展新的订单类型,
package notusingMode;

//既然要实现通用的订单处理,而不关心具体实现,需要定义一个订单的接口
public interface OrderApi {
//获取订单产品数量
	public int getOrderProductNum();
	
	//设置订单产品数量
	public void setOrderProductNum(int num);
}

package notusingMode;

public class PersonalOrder implements OrderApi {
//	产品数量
	private int productNum;
	
	private String customerName; //订购人员姓名
	
	private String productId; // 订购的产品编号

	@Override
	public int getOrderProductNum() {
		return productNum;
	}

	@Override
	public void setOrderProductNum(int num) {

		this.productNum = num;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getProductId() {
		return productId;
	}

	public void setProductId(String productId) {
		this.productId = productId;
	}
	
	public String toString(){
		return "本个人订单的订购人是="+this.customerName+",订购产品是="+this.productId+",订购数量是="+this.productNum;
	}

}


package notusingMode;

public class CompanyOrder implements OrderApi {
	// 产品数量
	private int productNum;

	private String companyName; // 订购公司名称

	private String productId; // 订购的产品编号

	@Override
	public int getOrderProductNum() {
		return productNum;
	}

	@Override
	public void setOrderProductNum(int num) {
		this.productNum = num;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public String getProductId() {
		return productId;
	}

	public void setProductId(String productId) {
		this.productId = productId;
	}
	
	public String toString(){
		return "本公司订单的公司名称是="+this.companyName+",订购产品是="+this.productId+",订购数量是="+this.productNum;
	}

}

业务逻辑
package notusingMode;
//处理订单的业务对象
public class OrderBusiness {

	//保存订单
	public void saveOrder(OrderApi order){
		//等具体实现
		
//		1。		判断订单的产品数量是否大于1000?
		while(order.getOrderProductNum()>1000){
			//2, 如果大于,继续拆分
//			2.1  再创建一个订单,跟传入的订单除了数量不一样外,其它都一样
			OrderApi newOrder = null;
			
			//问题产生了,如何新建一个订单????传入的参数是订单接口,根本不知道具体实现,一个简单的解决方案,使用
//			instanceof,仍然有问题,业务处理知道了订单的具体实现
			
			if(order instanceof PersonalOrder){
				PersonalOrder p1 = (PersonalOrder) order;
				PersonalOrder p2 = new PersonalOrder();
				p2.setCustomerName(p1.getCustomerName());
				p2.setProductId(p1.getProductId());
				p2.setOrderProductNum(1000); //产品数量为1000
				
				newOrder = p2;
			}
			
			else if(order instanceof CompanyOrder){
				CompanyOrder c1 = (CompanyOrder) order;
				CompanyOrder c2 = new CompanyOrder();
				c2.setCompanyName(c1.getCompanyName());
				c2.setProductId(c1.getProductId());
				c2.setOrderProductNum(1000); //产品数量为1000
				
				newOrder = c2;
			}
			
			//原来的订单保留,把数量设置成减少1000
			
			order.setOrderProductNum(order.getOrderProductNum()-1000);
			
			//然后是业务功能处理,省略了,打印输出,看一下
			System.out.println("拆分生成订单=="+newOrder);
			
			
		}
		//不超过1000,就直接进入业务处理
		System.out.println("订单=="+order);
		
	}
	
}

客户端:
package notusingMode;

public class Client {

	public static void main(String[] args) {

		PersonalOrder po = new PersonalOrder();
		
		
//		设置订单数据
		po.setOrderProductNum(2980);
		po.setCustomerName("John");
		po.setProductId("产品001");
		
		//这里简化了,连业务接口都没有
		OrderBusiness ob = new OrderBusiness();
		ob.saveOrder(po);
	}

}


上面的问题描述一下:已经有了某个对象实例后,如何能够快速简单地创建出更多的这种对象??如上面问题,就是已经有了接口类型的对象实例,然后在方法中需要创建出
更多的这种对象。怎么解决??
原型模式(prototype)
定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

原型模式会要求对象实现一个可以”克隆“自身的接口,这样就可以通过拷贝或者可同一个实例对象本身来创建一个新的实例。
这样一来,通过原型实例创建新的对象,就不需要关心这个实例本身的类型,也不关心它的具体实现,只要它实现类克隆自身的方法,就可以
通过这个方法来获取新的对象,无需再去通过new 创建对象。

原型模式的结构:
Prototype:声明一个克隆自身的接口,用来约束要想克隆自己的类,要求他们都要实现这里定义的克隆方法
ConcretePrototype:实现Prototype接口的类,这些类真正实现类克隆自身的功能
Client:使用原型的客户端,首先要获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例

package prototype;

public interface Prototype {

//	克隆自身的方法
	public Prototype clone();
}


package prototype;

public class ConcretePrototype1 implements Prototype {

	@Override
	public Prototype clone(){
		//创建一个自身对象
		Prototype p = new ConcretePrototype1();
		return p;
	}
}


package prototype;

public class ConcretePrototype2 implements Prototype {
	@Override
	public Prototype clone(){
		//创建一个自身对象
		Prototype p = new ConcretePrototype2();
		return p;
	}
}


package prototype;

public class Client {
	private Prototype prototype; // 持有需要使用的原型接口对象

	// 传入需要使用的原型接口对象,如果是业务处理,传入需要使用的订单接口对象
	public Client(Prototype prototype) {
		this.prototype = prototype;
	}

	public void oeration() {
		// 需要创建原型接口对象
		Prototype newPrototype = prototype.clone();

	}
}


用原型模式解决问题,订单接口就相当于Prototype,而PersonalOrder与CompanyOrder就相当于ConcretePrototype,业务处理对象
OrderBusiness就相当于使用原型的客户端。
package prototypeSolve;

//既然要实现通用的订单处理,而不关心具体实现,需要定义一个订单的接口
package prototypeSolve;

public class PersonalOrder implements OrderApi {
//	产品数量
	private int productNum;
	
	private String customerName; //订购人员姓名
	
	private String productId; // 订购的产品编号

	@Override
	public int getOrderProductNum() {
		return productNum;
	}

	@Override
	public void setOrderProductNum(int num) {

		this.productNum = num;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getProductId() {
		return productId;
	}

	public void setProductId(String productId) {
		this.productId = productId;
	}
	
	public String toString(){
		return "本个人订单的订购人是="+this.customerName+",订购产品是="+this.productId+",订购数量是="+this.productNum;
	}
	public OrderApi clone(){
		PersonalOrder personalOrder = new PersonalOrder();
		personalOrder.setCustomerName(this.customerName);
		personalOrder.setOrderProductNum(this.productNum);
		personalOrder.setProductId(this.productId);
		return personalOrder;
//		如果直接是return (this);返回的是同一个对象引用,对克隆对象的操作会影响到原操作
	}
}


package prototypeSolve;

public class CompanyOrder implements OrderApi {
	// 产品数量
	private int productNum;

	private String companyName; // 订购公司名称

	private String productId; // 订购的产品编号

	@Override
	public int getOrderProductNum() {
		return productNum;
	}

	@Override
	public void setOrderProductNum(int num) {
		this.productNum = num;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public String getProductId() {
		return productId;
	}

	public void setProductId(String productId) {
		this.productId = productId;
	}
	
	public String toString(){
		return "本公司订单的公司名称是="+this.companyName+",订购产品是="+this.productId+",订购数量是="+this.productNum;
	}
	public OrderApi clone(){
		CompanyOrder companyOrder = new CompanyOrder();
		companyOrder.setCompanyName(this.companyName);
		companyOrder.setOrderProductNum(this.productNum);
		companyOrder.setProductId(this.productId);
		return companyOrder;
//		如果直接是return (this);返回的是同一个对象引用,对克隆对象的操作会影响到原操作
	}
}


package prototypeSolve;

//处理订单的业务对象
public class OrderBusiness {

	// 保存订单
	public void saveOrder(OrderApi order) {
		// 等具体实现

		// 1。 判断订单的产品数量是否大于1000?
		while (order.getOrderProductNum() > 1000) {
			// 2, 如果大于,继续拆分
			// 2.1 再创建一个订单,跟传入的订单除了数量不一样外,其它都一样
			OrderApi newOrder = order.clone();
			newOrder.setOrderProductNum(1000);

			// 原来的订单保留,把数量设置成减少1000

			order.setOrderProductNum(order.getOrderProductNum() - 1000);

			// 然后是业务功能处理,省略了,打印输出,看一下
			System.out.println("拆分生成订单==" + newOrder);

		}
		// 不超过1000,就直接进入业务处理
		System.out.println("订单==" + order);

	}

}

package prototypeSolve;

public class Test {

	public static void main(String[] args) {

		OrderApi po = new PersonalOrder();

		po.setOrderProductNum(100);

		System.out.println("这是第一次获取的对象实例====" + po.getOrderProductNum());
		OrderApi po1 = po.clone();   //接口上定义的clone方法
		po1.setOrderProductNum(80);
		System.out.println("输出克隆出来的对象实例====" + po1.getOrderProductNum());
		System.out.println("再次输出原型实例====" + po.getOrderProductNum());
	}

}

原型模式功能:
(1)通过克隆来创建新的对象实例
(2)为克隆出来的新的对象实例复制原型实例属性的值
克隆和new,克隆方法得到的一个实例,通常属性是有值的,new一个实例对象,通常没有值或是默认值。

原型实例和克隆出来的实例,本质上是不同的实例,克隆完成后,它们之间没有关联的,即克隆的实例的属性值的改变不会影响原型实例
java中的克隆方法,是Object对象的方法protected Object clone()  throws CloneNotSupportedException
如何使用java中的克隆方法来实现原型模式??见包javaClonePrototype
需要克隆功能的类,只需实现Cloneable接口即可。
无论是自己实现克隆方法,还是采用java中的克隆方法,都存在深度克隆和浅度克隆的问题
深度克隆:除了浅度克隆,还负责克隆引用类型的数据,基本上是被克隆实例的属性数据都被克隆出来。
浅度克隆:只负责克隆按值传递的数据(比如基本数据类型,String类型)
深度克隆还有一个特定,如果被克隆的对象里面的属性数据是引用类型,则需要一直递归地克隆下去。意味着深度克隆成功,必须
整个克隆所涉及的对象都有正确实现克隆方法,如果其中有一个方法没有正确实现克隆,那么就会导致克隆失败。
在调用super.clone()方法进行克隆时,java先开辟一块内存空间,然后把实例对象的值原样拷贝过去,对于基本数据类型可以,但对于引用类型
拷贝的就是内存地址,所以克隆后的对象实例和原型对象指向同一块地址空间,要想正确地执行深度拷贝,必须手工对每个引用类型的属性进行克隆。
如果一个系统中的原型的数目不固定,比如系统中的原型可以被动态地创建和销毁,就需要维护一个档期可用的原型的注册表,这个注册表就称为原型管理器。
也相当于一个资源管理器,即一个缓冲资源的实现。
原型模式的优缺点:
优点:对客户端隐藏具体的实现类型,在运行时动态改变具体的实现类型
缺点:每个原型的子类都必须实现clone的操作,尤其在包含引用类型的对象时,clone方法会比较麻烦
本质:克隆生成对象。
原型模式通常被归类为创建型的模式,因为它可以生成新的对象实例。
全部代码见附件:
分享到:
评论

相关推荐

    c++-设计模式之原型模式(Prototype Pattern)

    原型模式(Prototype Pattern)是一种创建型设计模式,允许通过复制现有对象来创建新对象,而不是通过类构造器。这种模式常用于需要频繁创建相似对象的场景,能够提高性能并减少内存使用。 原型模式的组成 原型接口...

    设计模式C++学习之原型模式(Prototype)

    本篇文章将深入探讨“原型模式(Prototype)”这一经典的设计模式,它是面向对象设计的一个重要概念,尤其在C++编程中有着广泛的应用。 原型模式是一种创建型设计模式,它的核心思想是通过复制已有对象来创建新对象,...

    设计模式之Prototype(原型)

    "原型"(Prototype)设计模式是其中的一种,它的主要目标是通过复制现有的对象来创建新的对象,而不是通过构造函数来创建新实例。这种方法尤其适用于当创建新对象的过程复杂或者昂贵时,例如,当对象需要大量初始化...

    设计模式 创建型模式 Prototype模式(原型)

    Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。...

    创建型模式之原型模式(Prototype Pattern)

    在软件设计中,原型模式是一种创建型设计模式,它提供了一种通过复制已有对象来创建新对象的方式,避免了重复的构造过程,提高了代码的效率和可维护性。原型模式的核心思想是利用对象的克隆功能来实现新对象的创建,...

    原型模式(Prototype)

    原型模式是一种创建型设计模式,它提供了一种通过复制已有对象来创建新对象的方式,而不是通过传统的构造函数。这种模式在系统中需要创建大量相似对象时特别有用,可以提高效率并减少内存开销。在Java、C#等面向对象...

    原型模式(ProtoType)C#应用案例

    原型模式(Prototype)是一种软件设计模式,主要用于简化创建对象的过程,尤其当对象的构造过程复杂时。在C#中,我们可以利用接口或者继承来实现这一模式。本案例将深入探讨如何在C#环境中运用原型模式。 首先,...

    [创建型模式]设计模之原型模式(Prototype Pattern)

    **原型模式(Prototype Pattern)**是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而不是通过构造函数或工厂方法。这种模式的核心在于,它提供了一种更高效、更灵活的方式来创建新实例,特别是在...

    原型模式prototype

    **原型模式(Prototype)**是软件设计模式中的一种,它属于创建型模式,主要用于简化对象的创建过程,通过复制已有对象来生成新对象,避免了重复的构造过程,提高了代码的效率和可维护性。在Java、C#等面向对象语言...

    通过python实现原型模式(Prototype Pattern).rar

    原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新的对象,而不是通过传统的构造函数或类来实例化对象。原型模式在需要创建大量相似对象且创建过程较为耗时或复杂时非常有用。 在...

    设计模式之原型模式

    **原型模式(Prototype Pattern)**是一种创建型设计模式,它提供了一种创建对象的最佳方式,特别是在需要大量相似对象时,可以显著提高效率。在C#中,原型模式允许我们通过复制现有的对象来创建新对象,而不是通过...

    android设计模式之原型模式

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

    iOS设计模式-原型设计模式

    本文将详细探讨"原型设计模式"(Prototype Design Pattern)及其在iOS中的应用。 原型设计模式是一种创建型设计模式,它通过复制已有对象来创建新对象,而不是通过构造函数或者工厂方法。这种模式主要用于减少创建...

    IOS设计模式浅析之原型模式(Prototype)--copy - iOS知识库1

    iOS中的原型模式(Prototype)是一种设计模式,它允许我们通过复制已有对象来创建新的对象,而无需知道具体的创建过程。这种模式在某些情况下能够提高代码的可复用性和效率,特别是当创建新对象的步骤复杂时。 原型...

    设计模式的原型模式的例子

    原型模式(Prototype Pattern)是软件设计模式中的一种结构型模式,它的主要目的是通过复制已有对象来创建新对象,从而减少创建新对象的成本。在原型模式中,类的实例化过程被替换为对已有实例的克隆操作,尤其适用...

    23种设计模式之Prototype模式代码

    **原型模式(Prototype模式)**是软件设计模式中的一个经典模式,属于创建型模式。它提供了一种通过复制现有的对象来创建新对象的方式,而无需知道具体创建过程的细节。这种模式在需要频繁创建相似对象时非常有用,...

    原型模式(Prototype Pattern)原理图

    原型模式是一种创建型设计模式,它通过复制一个现有的对象来创建新的对象,而不是通过调用构造函数的方式。这种方式可以在运行时动态地创建和修改对象,而不需要知道具体的创建细节 。 原型模式的基本概念包括以下...

    Prototype模式

    **原型模式(Prototype Pattern)**是一种创建型设计模式,它提供了一种通过复制已有对象来创建新对象的方式,而不是通过构造函数。在某些情况下,当创建新对象的成本非常高时(例如,对象需要大量的初始化操作或者从...

Global site tag (gtag.js) - Google Analytics