通过序列化的方式实现深拷贝

    [Serializable]
public class Person:ICloneable
{
public string Name { get; set; }
public int Age { get; set; }
public List<Friend> FriendList { get; set; }
public object Clone()
{
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, this);
memoryStream.Position = ;
Person p = (Person)formatter.Deserialize(memoryStream);
return p;
}
}
[Serializable]
public class Friend
{
public string Name { get; set; }
public int Age { get; set; }
}

在开发中如果我们希望快速的创建一个对象,并且该对象和原有的对象拥有相同的数据,并且和原有的对象不相干,那么我们就可以这样做

第一步:

假如我需要快速创建一个Person对象,然后和某个Person对象相同,如果我们我们只需要Person对象中的属性不引用其他数据信息,可以使用浅拷贝;

如果我们需要Person对象中所有的信息,包括引用的数据信息,可以使用深拷贝

第二步:

在Person类中实现Cloneable接口,重写clone()方法,如果是浅拷贝,只需要直接调用父类的clone()方法就行,如果是深拷贝,需要在clone()方法中重新开辟引用字段所需的内存

代码如下:

Person.java

package com.designpattern.prototype;

import java.util.ArrayList;
import java.util.List; public class Person implements Cloneable {
private String name;
private int age; //朋友
private List<String> friends; public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
} /**
* 实现浅拷贝
*/
// protected Person clone(){
//
// try {
// return (Person)super.clone();
// } catch (CloneNotSupportedException e) {
// e.printStackTrace();
// return null;
// }
//
// } /**
* 实现深拷贝
*/
protected Person clone(){ try {
List<String> newfriends = new ArrayList<String>();
for (String friend : this.getFriends()) {
newfriends.add(friend);
}
Person person = (Person)super.clone();
person.setFriends(newfriends);
return person;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
} }
}

MainClass.java

package com.designpattern.prototype;

import java.util.ArrayList;
import java.util.List; public class MainClass { public static void main(String[] args) {
//假如我需要快速创建一个Person对象,然后和某个Person对象相同,如果我们我们只需要Person对象中的属性不引用其他数据信息,可以使用浅拷贝
//如果我们需要Person对象中所有的信息,包括引用的数据信息,可以使用深拷贝
/*
* 浅拷贝
*/
// Person person = new Person();
// person.setName("jack");
// person.setAge(18);
//
// Person person2 = person.clone();//相当于重新开辟一块内存空间,和person互不干扰
// person2.setName("jack1");
//
// System.out.println(person.getName());
// System.out.println(person2.getName()); Person person = new Person();
person.setName("jack");
person.setAge();
List<String> friends = new ArrayList<String>();
friends.add("p1");
friends.add("p2");
person.setFriends(friends); Person person2 = person.clone();
person2.setName("jack1");
friends.add("p3");//person 引用friends,friends改变,person的friends就会改变,如果用浅拷贝,person2也会跟着改变
//如果用深拷贝,person2不会跟着改变,因为person2的friends和person的friends没有指向同一块内存 System.out.println(person.getName());
System.out.println(person2.getName());
System.out.println(person.getFriends());
System.out.println(person2.getFriends());
} }

一、什么是原型模式

Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。

二、原型模式的特点

1. 由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。

2.目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。

3.根据对象克隆深度层次的不同,有浅度克隆与深度克隆。

三、原型模式应用场景

- 在创建对象的时候,我们不只是希望被创建的对象继承其基类的基本结构,还希望继承原型对象的数据。

- 希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)。

- 隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。

.Net Framework源代码中的模式之Prototype(原型模式)

转载地址:http://kb.cnblogs.com/page/68814/

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

  以.NET Framework 2.0 System.Collections中类为例。

  System.Collections. ICollection

public interface ICollection : IEnumerable
{
}

  System.Collections. ICloneable

public interface ICloneable
{
  object Clone();
}

  System.Collections. Stack

public class Stack : ICollection, ICloneable
{
  public virtual Object Clone()
  {
    Stack s = new Stack(_size);
    s._size = _size;
    Array.Copy(_array, 0, s._array, 0, _size);
    s._version = _version;
    return s;
  }
}

 

  System.Collections. Queue

public class Queue : ICollection, ICloneable
{
  public virtual Object Clone()
  {
   Queue q = new Queue(_size);
   q._size = _size;
   int numToCopy = _size;
   int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy;
   Array.Copy(_array, _head, q._array, 0, firstPart);
   numToCopy -= firstPart;
   if (numToCopy > 0)
   Array.Copy(_array, 0, q._array, _array.Length - _head, numToCopy);
   q._version = _version;
   return q;
  }
}

  调用代码

public class Client
{
  public static void Main()
  {
    Stack myStack = new Stack();
    myStack.Push("Hello");
    myStack.Push("World");
    myStack.Push("!");
    Stack myStackCopy = (Stack)myStack.Clone(); 
    foreach (string s in myStackCopy)
    {
      Console.Write(s);
    }
    Console.WriteLine();
    Console.ReadLine();
  }
}

 

  在.NET Framework中,可以通过实现ICloneable接口来实现原型模式,ICloneable接口只有一个Clone方法。克隆的实现方法有两种:浅拷贝(shallow copy)与深拷贝(deep copy)。

  浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。而深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式,所以如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个深拷贝的话,我们将创建一个新的对象和一个新的字符串--新对象将引用新字符串。需要注意的是执行深拷贝后,原来的对象和新创建的对象不会共享任何东西;改变一个对象对另外一个对象没有任何影响。

  对于值类型,浅拷贝通过赋值等操作直接实现,将对象中的值类型的字段拷贝到新的对象中;深拷贝和浅拷贝相同,通过赋值等操作直接实现,将对象中的值类型的字段拷贝到新的对象中。 对于引用类型,浅拷贝通过MemberwiseClone 方法创建一个浅副本,方法是创建一个新对象,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用原始对象,与原对象引用同一对象;深拷贝拷贝对象应用,也拷贝对象实际内容,也就是创建了一个新的对象,改变新对象不会影响到原始对象的内容。

  在下列情况下,应当使用Prototype模式:

  • 当一个系统应该独立于它的产品创建,构成和表示时;
  • 当要实例化的类是在运行时刻指定时,例如,通过动态装载;
  • 为了避免创建一个与产品类层次平行的工厂类层次时;
  • 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

设计模式学习之原型模式(Prototype,创建型模式)(5)的更多相关文章

  1. 设计模式学习之单例模式(Singleton,创建型模式)(4)

    假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...

  2. 设计模式05: Prototype 原型模式(创建型模式)

    Prototype 原型模式(创建型模式) 依赖关系的倒置抽象不应该依赖于实现细节,细节应该依赖于抽象.对所有的设计模式都是这样的. -抽象A直接依赖于实现细节b -抽象A依赖于抽象B,实现细节b依赖 ...

  3. 原型模式 prototype 创建型 设计模式(七)

    原型模式  prototype 意图 用原型实例指定需要创建的对象的类型,然后使用复制这个原型对象的方法创建出更多同类型的对象   显然,原型模式就是给出一个对象,然后克隆一个或者更多个对象 小时候看 ...

  4. Prototype,创建型模式

    读书笔记_探索式测试_混合探索式测试   一.测试场景 1.讲述用户故事 2.描述需求 3.演示产品功能 4.演示集成场景 5.描述设置和安装 6.描述警告和出错情况 二.使用基于场景的探索式测试 1 ...

  5. 设计模式04: Factory Methord 工厂方法模式(创建型模式)

    Factory Methord 工厂方法模式(创建型模式) 从耦合关系谈起耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关的模块都要随之变更 -模块与模块之间的 ...

  6. 设计模式03: Builder 生成器模式(创建型模式)

    Builder生成器模式(创建型模式) Builder模式缘起假设创建游戏中的一个房屋House设施,该房屋的构建由几个部分组成,且各个部分富于变化.如果使用最直观的设计方法,每个房屋部分的变化,都将 ...

  7. (转)Java经典设计模式(1):五大创建型模式(附实例和详解)

    原文出处: 小宝鸽 一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代 ...

  8. 设计模式01: Singleton 单例模式(创建型模式)

    Singleton 单例模式(创建型模式) 动机(Motivation)当进行软件开发是会有这样一种需求:在系统中只有存在一个实例才能确保它们的逻辑正确性.以及良好的效率.这应该是类设计者的责任,而不 ...

  9. Java设计模式——建造者模式(创建型模式)

    概述   建造者模式也称为生成器模式,是一种对象创建型模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象.   建造者模式意在为重叠构造 ...

随机推荐

  1. autofac 初步学习

    //数据处理接口 public interface IDal<T> where T : class { void Insert (T model); void Update(T model ...

  2. Jquery——思维导图

  3. Centos目录结构详细版

    使用linux也有一年多时间了  最近也是一直在维护网站系统主机  下面是linux目录结构说明 本人使用的是centos系统,很久没有发表博文了 近期会整理自己所用所了解知识点,发表linux相关的 ...

  4. Bookmarklet

    学习 http://www.ruanyifeng.com/blog/2011/06/a_guide_for_writing_bookmarklet.html

  5. fatl exception occurred异常/错误的一种可能情况

    如果,有可能是 java.lang.ClassLoader类内部出错,请自行检查

  6. “System.Transactions.Diagnostics.DiagnosticTrace”的类型初始值设定项引发异常[WCF]

    未处理System.TypeInitializationException  HResult=-2146233036  Message=“System.ServiceModel.Diagnostics ...

  7. 我的电脑右下角的日期也不见了只剩下时间,Win7系统,请问是什么原因啊?

    A:今天是2013/10/10,日期变为八位,宽度就不够了,把任务栏拉宽就好了 Q:win7 任务栏时间区可以拉宽吗?使之显示日期等 A:你的任务栏锁定了的,右键单击任务栏-锁定任务栏前面的勾去掉,鼠 ...

  8. Responsive设计的十个基本技巧(转)

    什么是Responsive设计?有的同学认为Responsive设计是自适应布局,也有的同学认为Responsive是网格布局.其实这些想法都不正确.Wikipedia对Responsive做 了详细 ...

  9. ubuntu下手把手教你搭建SVN服务器

    序,我的ubuntu服务器版本是14.04 ,x64(64位)操作系统,服务器在国内. 目录 一.安装SVN服务器 1 安装svn2 创建目录3 创建版本仓库4 配置5 启动SVN服务器6 验证svn ...

  10. Entity Framework 系统约定配置

    前言 Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来越复杂,大家都试图将软件设计的越来越灵活,很多内容我们都希望是可配 ...