23种设计模式——原型模式

原型(Proxotype)模式

本质:克隆生成对象

目的:给出一个原型对象,指出要创建的对象类型,通过克隆方法创建更多同类型的对象

实现方式:

  • 浅复制:只复制按值传递的对象(基础数据类型,String类型)
  • 深复制:按值传递的类型,引用类型都复制

若成员变量无引用类型,浅拷贝clone即可;若引用类型的成员变量很少,可考虑递归实现clone,否则推荐序列化。

构成:

客户(Client):
提出创建对象的请求
抽象原型(Prototype):
是接口或抽象类,给出所有的具体原型类所需的方法。

  • 在C#中,需要实现ICloneable接口,调用Clone方法。
  • 在Java中,需要实现java.lang.Cloneable接口,调用clone方法。

具体原型(Concrete Prototype):
是被复制的对象,实现抽象原型类所要求的方法。

适用场景

  • 需要生成一大批很相像的类的对象时,不用每次去做重复的赋值工作

优点

  • 创建新的对象比较复杂时,可简化对象的创建过程,同时提高效率
  • 不用重新初始化对象,动态地获得对象运行时的状态。
  • 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码

缺点

  • 如果克隆引用数据类型,需要递归克隆

原型模式VS工厂模式

原型模式可以替代工厂模式,并且更方便、灵活。

  • 工厂模式生产产品是利用继承。生成的产品是由同一个抽象产品类派生出来的。如果要生成一类产品,就要引入一个抽象产品类,再由它派生出具体产品。
  • 在原型模式中,可以定义一个这样的“抽象产品——具体产品”层次,再利用具体产品本身的clone功能来生产具体产品。
  • 在原型模式中,每个具体产品就是工厂模式里的具体工厂+具体产品(因为每个具体产品都具有生成自己的功能,这正是工厂的作用)。

实例

复印简历

public class WorkExperience implements Cloneable{
	private String workDate;
	private String company;
	
	
	public WorkExperience(String workDate, String company) {
		super();
		this.workDate = workDate;
		this.company = company;
	}
	
	public String getWorkDate() {
		return workDate;
	}
	public void setWorkDate(String workDate) {
		this.workDate = workDate;
	}
	public String getCompany() {
		return company;
	}
	public void setCompany(String company) {
		this.company = company;
	}
	
	public Object clone() {
		return this;
	}

}
public class Resume implements Cloneable{
	private String name;
	private String sex;
	private String age;
	private WorkExperience work;

	public Resume(String name) {
		super();
		this.name = name;
	}
	

	public Resume(String name, String sex, String age, WorkExperience work) {
		super();
		this.name = name;
		this.sex = sex;
		this.age = age;
		this.work = work;
	}

	
	public void setWorkExperience(String workDate,String company) {
		this.work.setWorkDate(workDate);
		this.work.setCompany(company);
	}
	

	@Override
	public String toString() {
		return "Resume [name=" + name + ", sex=" + sex + ", age=" + age + ", work=" + work + "]";
	}
	

	public Object clone() throws CloneNotSupportedException {
		//super调用的是接口中的clone(),this调用的是自己的clone
		Resume obj=(Resume)super.clone();
		obj.work=(WorkExperience)work.clone();
		return obj;
	}
	
}
public class Test {

	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		WorkExperience work=new WorkExperience("2019-2020","XX公司");
		Resume r1=new Resume("小李","男","26",work);
		System.out.println(r1);
		Resume r2=(Resume) r1.clone();
		r2.setWorkExperience("2020-2022", "YY公司");
		System.out.println(r2);
		
	}

}

订单系统

创建一系列不同类型的对象并不同的方式对其进行配置。 如果所需对象与预先配置的对象相同, 那么你只需克隆原型即可, 无需新建一个对象。
支持克隆的对象即为原型(该问题中为订单)
浅拷贝:拷贝基本数据类型 如 id,库存量
深拷贝:拷贝引用数据类型 如 产品
 

重写了java.lang.Cloneable接口中的clone()方法

public class Order implements Cloneable{
	private int id;//订单id
	private long num;//库存量
	private Product product;//产品
	private String username;//订购人
	
	public Order(int id, long num, Product product,String username) {
		super();
		this.id = id;
		this.num = num;
		this.product = product;
		this.username=username;
	}
	
	
	public String getUsername() {
		return username;
	}


	public void setUsername(String username) {
		this.username = username;
	}


	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public long getNum() {
		return num;
	}
	public void setNum(long num) {
		this.num = num;
	}
	public Product getProduct() {
		return product;
	}
	public void setProduct(Product product) {
		this.product = product;
	}
	
	
	
	@Override
	public String toString() {
		return "Order [id=" + id + ", num=" + num + ", product=" + product + ", username=" + username + "]";
	}


	protected Object clone() throws CloneNotSupportedException {
		Order order=(Order) super.clone();
		order.product=(Product)this.product.clone();
		return order;
	}
	
	
}
public class Product {
	private String name;//产品名
	private int price;//产品价格
	
	
	public Product(String name, int price) {
		super();
		this.name = name;
		this.price = price;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public int getPrice() {
		return price;
	}


	public void setPrice(int price) {
		this.price = price;
	}


	protected Object clone() {
		return this;
	}


	@Override
	public String toString() {
		return "[name=" + name + ", price=" + price + "]";
	}

	
}
public class Test {

	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		Product product=new Product("咖啡",10);
		Order order=new Order(1,200,product);
		int id=1;
		int num=200;
		while(order.getNum()>0) {
			Order neworder=(Order)order.clone();
			System.out.println(neworder);
			order.setNum(num--);
			order.setId(id++);
			
		}
	}

}

功能:每当订单的预定产品数量超过1000的时候,就需要把订单拆成两份订单来保存。如果拆成两份后还是超过1000,则继续拆分,直到每份产品预订数量不超过1000。

根据业务,目前的订单系统分成两种,一种是个人订单、一种是公司订单。

客户名称、产品对象(ID,Name),订购产品数量。

公司名称、产品对象(ID,Name),订购产品数量。

public class Test {
	 
	public static void main(String[] args) throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		Product product=new Product("咖啡",10);
		long num=10200;
		Order order=new Order(1,num,product,"公司订单");
		int id=1;
		long n=0;
		
		while(n<num) {
			order.setId(id++);
			Order neworder=(Order)order.clone();
			if(num-n>1000)
				neworder.setNum(1000);
			else
				neworder.setNum(num-n);
			System.out.println(neworder);
			n=n+1000;
		}
	}
 
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值