场景
场景1:
(1) 如果一个对象,我们希望拷贝一个这个对象
(2) 就是弄出来这个类的另外一个实例,实例的属性跟之前的实例是一模一样的
场景2:
(1)电商项目中各种对象VO,DTO,DO数据转换就可以使用原型模式,将一个基础数据拷贝到另一个数据对象里面去。
(2)刚从DAO中查询出来的一个ProductDO,包含了10个字段,然后接着在service中处理完成之后,需要返回一个ProductDTO,包含20个字段,此时别使用new ProductDTO,set,set...;应该使用原型模式,将ProductDO里面的数据直接拷贝到ProductDTO中去。
场景3:
(1)仓储中心创建的采购入库单和采购单大部分字段是一样的,创建采购入库单的时候,获取到的是一个采购单,此时你可能需要将采购单数据拷贝一份到采购入库单中去。
内容
1. 不使用设计模式
1.1 类图
1.2 代码
public class NonPattern2 {
/**
* 定义一个对象:里面有其他对象的引用,我们实现拷贝
*/
public static void main(String[] args) {
//1. 创建一个对象,进行拷贝
Product product = new Product("汽车", new Component("汽车轮胎"));
//2.手动来拷贝
Product copyedProduct = new Product(product.getName(),product.getComponent());
System.out.println("product:"+product);
System.out.println("copyedProduct:"+copyedProduct);
/**
* 输出:
* product:Product{name='汽车', component=Component{name='汽车轮胎'}}
* copyedProduct:Product{name='汽车', component=Component{name='汽车轮胎'}}
*/
}
//===================产品实体类====================
public static class Product{
private String name;
private Component component;
public Product(String name,Component component){
this.component =component;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", component=" + component +
'}';
}
}
public static class Component{
private String name;
public Component(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Component{" +
"name='" + name + '\'' +
'}';
}
}
}
2. 使用设计模式
- 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
- 这里实现原型拷贝最主要的是对象里面的clone方法。
2.1 类图
2.2 代码
public class PrototypePattern2 {
public static void main(String[] args) {
try {
Product product = new Product("汽车", new Component("汽车轮胎"));
Product copyedProduct = (Product) product.clone();
System.out.println("product:"+product);
System.out.println("copyedProduct:"+copyedProduct);
/**
* 输出:
* product:Product{name='汽车', component=Component{name='汽车轮胎'}}
* copyedProduct:Product{name='汽车', component=Component{name='汽车轮胎'}}
*/
}catch (Exception e){
e.printStackTrace();
}
}
//=====================产品类======================
public static class Product{
private String name;
private Component component;
public Product(String name,Component component){
this.name = name;
this.component = component;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//浅拷贝,就是我们现在的一个实现 就是仅仅简单的对当前所有的变量进行一个拷贝
// return new Product(getName(),getComponent());
// 深考别,递归对自己引用的对象也进行拷贝
return new Product(getName(),(Component) getComponent().clone());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", component=" + component +
'}';
}
}
public static class Component{
private String name;
public Component(String name){
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new Component(getName());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Component{" +
"name='" + name + '\'' +
'}';
}
}
}
3.总结
3.1 不使用设计模式对比
- 代码的拷贝逻辑,是每个要拷贝的调用方(main方法)自己来实现的;相同的拷贝逻辑会分散在很多不同的地方,如果拷贝逻辑改变了,多个调用的地方都要修改代码。
- 可维护性、可扩展性,很差。
3.2 使用原型模式
- 原对象拷贝直接使用原对象的clone方法,是在目标对象自身,而不是调用方,调用方不用关注拷贝逻辑。
- 扩展性强:如果目标对象添加了新属性,拷贝逻辑可直接在目标对象的clone()修改。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。