java 原型设计模式
来源:互联网 发布:c语言教程 编辑:程序博客网 时间:2024/05/27 09:46
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,也就是用原型实例
(也就是对象因为只有对象才可以称之为实例,对象肯定有它的属性) 通过拷贝把这些属性组建成一个新的对象.
结构和说明
先写一个简单的例子感受下原型模式的基本应用:
package com.zhimore.prototype1;
/**
* 声明一个克隆自身的接口
* @author Adminis
*
*/
public interface Prototype {
/**
* 克隆自身的方法
* @return 一个从自身克隆出来的对象
*/
public Prototype clone();
}
ConcretePrototype1.java 实现克隆的子类实现
package com.zhimore.prototype1;
public class ConcretePrototype1 implements Prototype {
@Override
public Prototype clone() {
//最简单的克隆,新建一个自身对象,由于没有属性,就不去复制值了
Prototype prototype = new ConcretePrototype1();
return prototype;
}
}
Client.java
package com.zhimore.prototype1;
public class Client {
/**
* 持有需要使用的原型接口对象
*/
private Prototype prototype;
/**
* 构造方法,传入需要使用的原型接口对象
* @param prototype 需要使用的原型接口对象
*/
public Client(Prototype prototype){
this.prototype = prototype;
}
/**
* 把传递过来的对象克隆一个新的对象
*/
public void operation(){
Prototype newPrototype = prototype.clone();
}
}
上面只是怎么为下面讲原型模式的预热而已,知道有这样的方法可以创建对象就行,下面通过一个例子来讲解一下原型模式的使用更好解决实际问题:
我们先不用模式的解决方案,然后再使用原型设计模式解决,对比下使用模式后的优点以及好处:
不用模式的解决方案:
先把订单这块有些操作行为抽象成一个接口:
IOrder.java
package com.zhimore.prototype2;
/**
* 订单的接口
* @author Adminis
*
*/
public interface IOrder {
/**
* 获取订单产品数量
* @return
*/
public long getOrderNum();
/**
* 设置订单产品数量
* @param num 订单产品数量
*/
public void setOrderNum(long num);
}
PersonalOrder.java 个人订单
package com.zhimore.prototype2;
/**
* 个人订单
* @author Adminis
*
*/
public class PersonalOrder implements IOrder {
/**
* 订购人员姓名
*/
private String customerName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private long orderProductNum = 0;
@Override
public long getOrderNum() {
return orderProductNum;
}
@Override
public void setOrderNum(long num) {
this.orderProductNum = 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.orderProductNum;
}
}
EnterpriseOrder.java 企业订单
package com.zhimore.prototype2;
public class EnterpriseOrder implements IOrder {
/**
* 企业名称
*/
private String enterpriseName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private long orderProductNum = 0;
@Override
public long getOrderNum() {
return orderProductNum;
}
@Override
public void setOrderNum(long num) {
this.orderProductNum = num;
}
public String getEnterpriseName() {
return enterpriseName;
}
public void setEnterpriseName(String enterpriseName) {
this.enterpriseName = enterpriseName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String toString(){
return "本企业订单的订购企业是="+this.enterpriseName+",订购产品是="+this.productId+",订购数量为="+this.orderProductNum;
}
}
OrderBusiness.java 处理订单的业务类
package com.zhimore.prototype2;
/**
* 处理订单的业务对象
* @author Adminis
*
*/
public class OrderBusiness {
public void saveOrder(IOrder order){
while(order.getOrderNum() > 1000){
//2:如果大于,还需要继续拆分
//2.1再新建一份订单,跟传入的订单除了数量不一样外,其他都相同
IOrder newOrder = null;
if(order instanceof PersonalOrder){
//创建相应的新的订单对象
PersonalOrder p2 = new PersonalOrder();
//然后进行赋值,但是产品数量为1000
PersonalOrder p1 = (PersonalOrder)order;
p2.setCustomerName(p1.getCustomerName());
p2.setProductId(p1.getProductId());
p2.setOrderNum(1000);
//然后再设置给newOrder
newOrder = p2;
}else if(order instanceof EnterpriseOrder){
//创建相应的订单对象
EnterpriseOrder e2 = new EnterpriseOrder();
//然后进行赋值,但是产品数量为1000
EnterpriseOrder e1 = (EnterpriseOrder)order;
e2.setEnterpriseName(e1.getEnterpriseName());
e2.setProductId(e1.getProductId());
e2.setOrderNum(1000);
//然后再设置给newOrder
newOrder = e2;
}
//2.2原来的订单保留,把数量设置成减少1000
order.setOrderNum(order.getOrderNum()-1000);
//然后是业务功能处理,省略了,打印输出,看一下
System.out.println("拆分生成订单=="+newOrder);
}
//3:不超过,那就直接业务功能处理,省略了,打印输出,看一下
System.out.println("订单=="+order);
}
}
测试类:
package com.zhimore.prototype2;
public class Client {
public static void main(String[] args) {
//创建订单对象,这里为了演示简单,直接new了
PersonalOrder op = new PersonalOrder();
//设置订单数据
op.setOrderNum(1500);
op.setCustomerName("赵菲");
op.setProductId("0001");
//这里获取业务处理的类,也直接new了,为了简单,连业务接口都没有做
OrderBusiness ob = new OrderBusiness();
//调用业务来保存订单对象
ob.saveOrder(op);
System.out.println("--------------------");
EnterpriseOrder enterpriseOrder = new EnterpriseOrder();
enterpriseOrder.setOrderNum(2001);
enterpriseOrder.setEnterpriseName("华为");
enterpriseOrder.setProductId("0002");
ob.saveOrder(enterpriseOrder);
}
}
打印信息:
拆分生成订单==本个人订单的订购人是=赵菲,订购产品是=0001,订购数量为=1000
订单==本个人订单的订购人是=赵菲,订购产品是=0001,订购数量为=500
--------------------
拆分生成订单==本企业订单的订购企业是=华为,订购产品是=0002,订购数量为=1000
拆分生成订单==本企业订单的订购企业是=华为,订购产品是=0002,订购数量为=1000
订单==本企业订单的订购企业是=华为,订购产品是=0002,订购数量为=1
从上面不使用设计模式的解决的问题何在呢?
现在使用原型设计模式方法实现上面的需求:
结构图:
对IOrder这个接口中添加一个方法:
/**
* 克隆方法
* @return 订单原型的实例
*/
public IOrder cloneOrder();
它的子类就变成这样:
package com.zhimore.prototype3;
/**
* 个人订单
* @author Adminis
*
*/
public class PersonalOrder implements IOrder {
/**
* 订购人员姓名
*/
private String customerName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private long orderProductNum = 0;
@Override
public long getOrderNum() {
return orderProductNum;
}
@Override
public void setOrderNum(long num) {
this.orderProductNum = 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.orderProductNum;
}
@Override
public IOrder cloneOrder() {
PersonalOrder personalOrder = new PersonalOrder();
personalOrder.setCustomerName(customerName);
personalOrder.setOrderNum(orderProductNum);
personalOrder.setProductId(productId);
return personalOrder;
}
}
业务类:
package com.zhimore.prototype3;
public class OrderBusiness {
/**
* 创建订单的方法
* @param order 订单的接口对象
*/
public void saveOrder(IOrder order){
//根据业务要求,当订单的预定的产品数量超过1000的时候,就需要把订单拆成两份订单
//当然如果要做好,这里的1000应该做成常量,这么做是为了演示简单
//1:判断当前的预定产品数量是否大于1000
while(order.getOrderNum() > 1000){
//2:如果大于,还需要继续拆分
//2.1再新建一份订单,跟传入的订单除了数量不一样外,其他都相同
IOrder newOrder = order.cloneOrder();
//然后进行赋值,产品数量为1000
newOrder.setOrderNum(1000);
System.out.println("old order num=="+order.getOrderNum()+" , new Order num==="+newOrder.getOrderNum());
//2.2原来的订单保留,把数量设置成减少1000
order.setOrderNum(order.getOrderNum()-1000);
//然后是业务功能处理,省略了,打印输出,看一下
System.out.println("拆分生成订单=="+newOrder);
}
//3:不超过,那就直接业务功能处理,省略了,打印输出,看一下
System.out.println("订单=="+order);
}
}
这个业务类改造就不需要依赖具体的实现了,而且扩展性也提高了,系统以后不管需要添加什么类型的订单都没问题,也不关心订单的具体实现(也就是订单中有什么方法) 业务是不是大大简化而且提高了扩展性
通过上面的例子对原型设计模式一些基本的总结:
上面的克隆是自己写的 其实java jdk中已经帮我们实现了克隆,它是定义在Object类中,我把Object中所有定义的方法截图看下:
深度克隆和纤度克隆
现在使用java jdk中自带的克隆
我们把PersonalOrder类中复写了clone了方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = null;
obj = super.clone();
return obj;
}
使用:
package com.zhimore.prototype3;
public class Client {
public static void main(String[] args) {
//先创建原型实例
PersonalOrder oa1 = new PersonalOrder();
//设置原型实例的订单数量的值
oa1.setOrderNum(100);
//为了简单,这里仅仅输出数量
System.out.println("这是第一次获取的对象实例==="+oa1.getOrderNum());
//通过克隆来获取新的实例
PersonalOrder oa2 = null;
try {
oa2 = (PersonalOrder)oa1.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//修改它的数量
oa2.setOrderNum(80);
//输出克隆出来的对象的值
System.out.println("输出克隆出来的实例==="+oa2.getOrderNum());
//再次输出原型实例的值
System.out.println("再次输出原型实例==="+oa1.getOrderNum());
}
}
打印效果:
这是第一次获取的对象实例===100
输出克隆出来的实例===80
再次输出原型实例===100
说明在克隆后改变了克隆对象的属性值 而不会影响之前对象的属性值
如果对克隆不是很熟悉的话 可以去网上找找文章写个demo就理解了,原型设计模式就讲到这里了!
- java 原型设计模式
- Java原型设计模式
- java设计模式(原型模式)
- java设计模式---原型模式
- java设计模式---原型模式
- java设计模式---原型模式
- Java设计模式---原型模式
- JAVA设计模式:原型模式
- java设计模式----原型模式
- JAVA 设计模式 - 原型模式
- 《Java设计模式》 原型模式
- Java设计模式 -- 原型模式
- Java设计模式--原型模式
- Java 设计模式-原型模式
- JAVA设计模式--原型模式
- java设计模式-原型模式
- Java设计模式--原型模式
- java设计模式,原型模式
- USACO-Section 4.1-PROB Beef McNuggets
- 关于隐藏Windows控制台的办法
- CView视图类
- iptables进行端口转发
- hdu 1239 Calling Extraterrestrial Intelligence Again
- java 原型设计模式
- HDU——1303Doubles(水题,试手二分查找)
- 【bzoj1295】[SCOI2009]最长距离 最短路
- 数据结构之---树
- 线程生命周期图解
- linux 安装 killall命令
- Nginx之location 匹配规则详解
- POJ 2774 Long Long Message
- linux--ubuntu下Vim安装失败