java23种设计模式—— 1、设计模式介绍
java23种设计模式—— 2、单例模式
java23种设计模式——3、工厂模式
java23种设计模式——4、原型模式
java23种设计模式——5、建造者模式
java23种设计模式——6、适配器模式java
这种模式是实现了一个原型接口,该接口用于建立当前对象的克隆。当直接建立对象的代价比较大时,则采用这种模式。例如,一个对象须要在一个高代价的数据库操做以后被建立。咱们能够缓存该对象,在下一个请求时返回它的克隆,在须要的时候更新数据库,以此来减小数据库调用。git
举个例子,就是当咱们须要给电脑安装win10系统时须要去官网上下载win10系统的安装包。而安装包的大小都是很耗时的,还须要另外一台电脑来操做。若是咱们下载了一个安装包放在咱们的u盘里,以后须要安装win10时是否是就省去了中间寻找,下载等时间呢github
原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码以下数据库
新建一个实体类Sheep实现Cloneable 接口,重写clone()方法设计模式
/** * @author codermy * @createTime 2020/5/14 */ public class Sheep implements Cloneable{ private String name; private int age; private String sex; 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; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Sheep(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } //克隆该实例,使用默认的clone方法 @Override protected Object clone() throws CloneNotSupportedException { Sheep sheep =null; sheep = (Sheep)super.clone(); return sheep; } }
测试缓存
/** * @author codermy * @createTime 2020/5/14 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { Sheep sheep = new Sheep("tom",1,"male"); Sheep sheep1 = (Sheep)sheep.clone(); System.out.println(sheep.hashCode()); System.out.println(sheep); System.out.println(sheep1.hashCode()); System.out.println(sheep1); sheep1.setAge(2); System.out.println(sheep1); System.out.println(sheep); } }
输出bash
1163157884 Sheep{name='tom', age=1, sex='male'} 1956725890 Sheep{name='tom', age=1, sex='male'} Sheep{name='tom', age=2, sex='male'} Sheep{name='tom', age=1, sex='male'}
在浅克隆中,被复制对象的全部普通成员变量都具备与原来对象相同的值,而全部的对其余对象的引用仍然指向原来的对象。也就是说,浅克隆仅仅复制所考虑的对象,不会复制它所引用的成员对象。ide
咱们先新建一个Pearson类,做为对象属性函数
/** * @author codermy * @createTime 2020/7/24 */ public class Person implements Cloneable{ String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(){ } public Person(String name){ this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
咱们先给Sheep实体类种添加一个对象属性
/** * @author codermy * @createTime 2020/6/16 */ public class Sheep implements Cloneable { private String name; private int age; private String sex; public Person owner;//对象引用 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; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Person getOwner() { return owner; } public void setOwner(Person owner) { this.owner = owner; } public Sheep(String name, int age, String sex, Person owner) { this.name = name; this.age = age; this.sex = sex; this.owner = owner; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", owner=" + owner + '}'; } //克隆该实例,使用默认的clone方法 @Override protected Object clone() throws CloneNotSupportedException { Sheep sheep =null; sheep = (Sheep)super.clone(); return sheep; } }
测试类中测试
/** * @author codermy * @createTime 2020/6/16 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person owner = new Person("马云"); Sheep sheep = new Sheep("tom",1,"male", owner);//新建sheep类 Sheep sheep1 = (Sheep)sheep.clone();//克隆该类 System.out.println(sheep.hashCode() + " " + sheep.owner.hashCode()); System.out.println(sheep + " "+ sheep.owner); System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode()); System.out.println(sheep1 + " " + sheep1.owner); sheep1.owner.setName("马化腾"); System.out.println(sheep.owner); System.out.println(sheep1.owner); } }
输出
1163157884 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'} 356573597 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'} Person{name='马化腾'} Person{name='马化腾'}
咱们能够看出浅克隆时对象的引用仅仅是指向了原空间,而并无复制对象。
在深克隆中,对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
将上面Sheep类中的clone方法改写
@Override protected Object clone() throws CloneNotSupportedException { Sheep sheep =null; sheep = (Sheep)super.clone(); sheep.owner = (Person) sheep.owner.clone();//引用对象的克隆方法 return sheep; }
测试类测试
public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person owner = new Person("马云"); Sheep sheep = new Sheep("tom",1,"male", owner); Sheep sheep1 = (Sheep)sheep.clone(); System.out.println(sheep.hashCode() + " " + sheep.owner.hashCode()); System.out.println(sheep + " "+ sheep.owner); System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode()); System.out.println(sheep1 + " " + sheep1.owner); sheep1.owner.setName("马化腾"); System.out.println(sheep.owner); System.out.println(sheep1.owner); } }
输出
1163157884 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'} 356573597 1735600054 Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'} Person{name='马云'} Person{name='马化腾'}
这时候咱们已经实现了深克隆,可是总以为有点“浅浅克隆”的意思,若是person类中还有对象引用那不就是。。
禁止套娃
两个实体类实现序列化接口
Person类
public class Person implements Serializable { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } public Person(String name){ this.name = name; } }
Sheep类
/** * @author codermy * @createTime 2020/6/16 */ public class Sheep implements Serializable { private String name; private int age; private String sex; public Person owner;//对象引用 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; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Person getOwner() { return owner; } public void setOwner(Person owner) { this.owner = owner; } public Sheep() { } public Sheep(String name, int age, String sex, Person owner) { this.name = name; this.age = age; this.sex = sex; this.owner = owner; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", owner=" + owner + '}'; } }
实现
** * @author codermy * @createTime 2020/7/24 */ public class Client { public static void main(String[] args) throws Exception { Person owner = new Person("马云"); Sheep sheep = new Sheep("tom",1,"male", owner); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(sheep); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); Sheep sheep1 =(Sheep) ois.readObject(); bos.flush();oos.flush(); bos.close();oos.close(); ois.close(); System.out.println("Sheep: " + sheep); System.out.println("Sheep1: " + sheep1); System.out.println("================================"); System.out.println("Sheep: " + sheep.hashCode() + "++++++++++" + sheep.owner.hashCode()); System.out.println("Sheep1: " + sheep1.hashCode() + "++++++++++" + sheep1.owner.hashCode()); System.out.println("================================"); sheep1.owner.setName("马化腾"); System.out.println("Sheep: " + sheep.owner); System.out.println("Sheep1: " + sheep1.owner); } }
输出
1163157884 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'} 356573597 1735600054 Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'} Person{name='马云'} Person{name='马化腾'}
优势:原型模式是在内存中二进制流的拷贝,要比new一个对象的性能要好,特别是须要产生大量对象时。
缺点:直接在内存中拷贝,构造函数是不会执行的。