zoukankan      html  css  js  c++  java
  • 设计模式学习--------10.原型模式学习

    场景:

          一个订单系统,里面有一个保存订单的业务功能。具体需求:每当订单的预订产品超过1000的时候,需要把订单拆分

    成两份订单。如果拆分成两份后还是超过1000,则继续拆分。订单类型分为个人订单和公司订单,不管是什么类型的订

    单,都要能够正常地处理.抽象的描述下就是已经有了某个对象实例后,如何能够快速的创建出更多的这种对象。


    定义:

          用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。


    角色:

    Prototype: 声明一个克隆自身的接口,用来约束想要克隆自己的类,要求他们都要实现这里定义的克隆方法。

    package com.kris.study;
    
    public interface Prototype {
         public Prototype cloneItem();
         public void display();
    }
    


    ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能

    package com.kris.study;
    
    public class ConcretePrototype2 implements Prototype {
    
    	@Override
    	public Prototype cloneItem() {
    		return new ConcretePrototype2();
    	}
    
    	@Override
    	public void display() {
    		System.out.println("ConcretePrototype2 display");
    	}
    
    }
    
    package com.kris.study;
    
    public class ConcretePrototype1 implements Prototype {
    	
    	@Override
    	public Prototype cloneItem() {
    		return new ConcretePrototype1();
    	}
    
    	@Override
    	public void display() {
    		System.out.println("ConcretePrototype1 display");
    	}
    
    }
    


    Client客户端:

    package com.kris.study;
    
    public class Client {
    	private Prototype prototype;
    
    	public Client(Prototype prototype){
    		this.prototype = prototype;
    	}
    	
    	public void operation(){
    		Prototype newPrototype = prototype.cloneItem();
    		newPrototype.display();
    	}
    	
    }
    


    使用JAVA中的克隆方法实现原型模式解决场景的问题:

    Order:订单类

    package com.kris.study;
    
    public abstract class Order implements Cloneable{
    	private String productId;
    	private int orderProductNum = 0;
    	
    	public abstract void setName(String name);
    	public abstract String display();
    	
    	public String getProductId() {
    		return productId;
    	}
    	public void setProductId(String productId) {
    		this.productId = productId;
    	}
    	public int getOrderProductNum() {
    		return orderProductNum;
    	}
    	public void setOrderProductNum(int orderProductNum) {
    		this.orderProductNum = orderProductNum;
    	}
    	@Override
    	public Object clone() throws CloneNotSupportedException {
    		return super.clone();
    	}
    }
    


    PersonalOrder:个人订单类

    package com.kris.study;
    
    public class PersonalOrder extends Order {
    
    	 private String personalName;
    	    
    		@Override
    		public String display() {
    		  return "PersonalName:"+personalName;
    		}
    
    
    		@Override
    		public void setName(String name) {
    			this.personalName = name;
    		}
    
    		
    }
    


    EnterpriseOrder:公司订单类

    package com.kris.study;
    
    public class EnterpriseOrder extends Order {
        private String enterpriseName;
        
    	@Override
    	public String display() {
    	  return "EnterpriseName:"+enterpriseName;
    	}
    
    
    	@Override
    	public void setName(String name) {
    		this.enterpriseName = name;
    	}
    }
    


    OrderBiz:订单业务

    package com.kris.study;
    
    public class OrderBiz {
       public void saveOrder(Order order){
    	   while(order.getOrderProductNum()>1000){
    		try {
    			Order newOrder = (Order) order.clone();
    			newOrder.setOrderProductNum(1000);
    			order.setOrderProductNum(order.getOrderProductNum()-1000);
    			System.out.println("new order info ==> name: "+newOrder.display()+" productId:"
    					+newOrder.getProductId()+" productNum:"+newOrder.getOrderProductNum());
    		} catch (CloneNotSupportedException e) {
    			e.printStackTrace();
    		}
    	   }
    	   System.out.println("old order info ==> name: "+order.display()+" productId:"
    				+order.getProductId()+" productNum:"+order.getOrderProductNum());
       }
    }
    


    Client:客户端

    package com.kris.study;
    
    public class Client {
       public static void main(String[] args) {
    	 Order order = new PersonalOrder();
    	 order.setName("John");
    	 order.setProductId("111");
    	 order.setOrderProductNum(3422);
    	 new OrderBiz().saveOrder(order);
       }
    }
    


    深克隆和浅克隆

    浅克隆:只负责克隆按值传递的数据(比如基本数据类型,String类型)。

    深克隆:除了浅克隆要克隆的值外,还负责克隆引用类型的数据。

    引用类型需要递归实现Cloneable接口。

    JAVA中实现深克隆:

    package com.kris.study;
    
    public class Product implements Cloneable {
        private String productId;
        private String name;
    	public String getProductId() {
    		return productId;
    	}
    	public void setProductId(String productId) {
    		this.productId = productId;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	@Override
    	public String toString() {
    		return "Product [productId=" + productId + ", name=" + name + "]";
    	}
        
        @Override
        public Object clone() throws CloneNotSupportedException {
        	return super.clone();
        }
    }
    
    package com.kris.study;
    
    public class PersonalOrder implements Cloneable {
         private String customerName;
         private Product product = null;
    	public String getCustomerName() {
    		return customerName;
    	}
    	public void setCustomerName(String customerName) {
    		this.customerName = customerName;
    	}
    	public Product getProduct() {
    		return product;
    	}
    	public void setProduct(Product product) {
    		this.product = product;
    	}
    	
    	@Override
    	public String toString() {
    		return "PersonalOrder [customerName=" + customerName + ", product="
    				+ product + "]";
    	}
    	
    	@Override
    	public Object clone() throws CloneNotSupportedException {
    		PersonalOrder obj = (PersonalOrder) super.clone();
    		//关键的一句话
    		obj.setProduct((Product) this.product.clone());
    		return obj;
    	}
    		
    }
    


    原理分析:

       本质:克隆生成新对象

       优点:对客户端隐藏具体实现

       缺点:每个原型的子类必须实现clone的操作。

       

  • 相关阅读:
    Scrapy框架-scrapy框架快速入门
    Scrapy框架-scrapy框架架构详解
    linux常用命令大全
    Redis常用命令大全
    centos7安装keepalived问题
    redis集群部署那点事
    centos7安装python3.6后导致防火墙功能无法正常工作的解决办法
    MySQL/Oracle视图的创建与使用
    通过sqoop将hdfs数据导入MySQL
    股票交易日定时爬取上交所/深交所所有股票行情数据存储到数据库
  • 原文地址:https://www.cnblogs.com/krislight1105/p/3748382.html
Copyright © 2011-2022 走看看