有合作社做网站得不,广告公司网站模板,西安建设厅网站首页,我想在家办个小型加工厂文章目录 概述类图原型模式优缺点优点缺点 代码实现 概述
在有些系统中#xff0c;往往会存在大量相同或者是相似的对象#xff0c;比如一个围棋或者象棋程序中的旗子#xff0c;这些旗子外形都差不多#xff0c;只是演示或者是上面刻的内容不一样#xff0c;若此时使用传… 文章目录 概述类图原型模式优缺点优点缺点 代码实现 概述
在有些系统中往往会存在大量相同或者是相似的对象比如一个围棋或者象棋程序中的旗子这些旗子外形都差不多只是演示或者是上面刻的内容不一样若此时使用传统的构造函数创建对象那么简单的对象还好遇到稍微复杂一点的对象就会耗时耗资源而使用原型设计模式会让对象的生成高效很多
类图 在本文中使用了人和身体的例子来演示原型模式假如咱要造一个人的对象需要设置人的属性姓名年龄等然后给他设置身体大脑等器官本例只是为了展示原型模式只简单的做了Person和Body的结合。 原型模式主要有三个角色 1.抽象原型类它定义了具体的原型对象必须实现的接口。如本例子中的IProtoType接口 2.具体原型类 实现抽象原型接口中的复制对象的方法比如本例中的实现了原型接口中的 clone(),deepClone()方法的Person类 3.访问类 使用具体原型类中的复制对象方法生成新的对象比如本例中中的Client 结合本文中的例子原型设计模式的类图如下所示 原型模式优缺点
优点
原型设计模式的优点主要有两点如下所示 1可以优化性能在JAVA语言中可以通过实现Cloneable接口重写clone方法来达到复制对象的目的这种方式是基于内存二进制流的复制在性能上比直接使用new关键字创建一个对象高很多。
2可以使用原型模式中的深克隆方式保存对象的状态我们可以使用原型模式将对象复制一份并将其状态保存起来。简化了创建对象的过程在需要的时候直接使用我们保存的对象例如遇到需要恢复到历史某一状态的需求时或者是需要实现撤销操作的需求时都可以考虑原型模式
缺点
当然万事万物有优点就会有缺点原型模式的缺点主要有三个如下所示 1需要为每个类都配置一个克隆方法 2clone方法位于类的内部当对已有的类进行修改的时候需要修改对应的实现代码。不符合开闭原则对修改关闭对扩展开放 3当实现深克隆时需要编写较为复杂的代码而且当对象之间存在多层嵌套引用时每一层对象对应的类都必须支持深克隆实现起来比较麻烦
深克隆不仅拷贝对象的本身而且拷贝对象包含的引用指向的所有对象 浅克隆仅拷贝对象的本身而不拷贝对象包含的引用指向的对象 使用一个例子解释深克隆和浅克隆
public class Person {private static final Long VERSION 1000L;private String name;private int age;private Body body;
// 省略构造函数以及get,set方法
}比如我们要拷贝上面的Person对象如果使用深克隆的方式拷贝这时候Person对象中包含的Body对象也会被拷贝也就是说深克隆拷贝出的对象和原来的对象是完全独立的我们修改新克隆出的对象不会影响原来的Person对象。假如使用浅克隆这时只会拷贝Person中包含的Body对象的引用也就是说使用浅克隆拷贝出来的新对象中包含的Body对象和原来的对象中包含的一样因为浅克隆将Body的引用拷贝给了新克隆出的对象这时候如果修改新克隆出的对象那么原来的Person对象的Body也会跟着变后面会有例子证实这点
代码实现
本文中我们使用人和身体的例子来演示原型设计模式。首先我们定义出原型模式的接口如下所示
public interface IPrototype extends Cloneable{Person deepClone() throws IOException, ClassNotFoundException;
}
原型模式的接口继承自Java的Cloneable接口其中包含了一个clone()方法用于实现浅克隆而我们定义的接口中 包含了一个deepClone()方法用于实现深克隆。
然后就是定义一个类实现原型设计模式的接口
public class Person implements IPrototype, Serializable {private static final Long VERSION 1000L;private String name;private int age;private Body body;public Person(String name, int age) {this.name name;this.age age;}public void setBody(Body body) {this.body body;}public Body getBody() {return body;}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;}Overridepublic Person clone() {try {return (Person) super.clone();} catch (CloneNotSupportedException e) {throw new AssertionError();}}public Person deepClone() throws IOException, ClassNotFoundException {// 将对象写入到流中ByteArrayOutputStream byteArrayOutputStream new ByteArrayOutputStream();ObjectOutputStream outputStream new ObjectOutputStream(byteArrayOutputStream);outputStream.writeObject(this);// 将对象从流中取出ByteArrayInputStream byteArrayInputStream new ByteArrayInputStream(byteArrayOutputStream.toByteArray());ObjectInputStream inputStream new ObjectInputStream(byteArrayInputStream);return (Person) inputStream.readObject();}Overridepublic String toString() {return Person{ name name \ , age age , body body };}
}需要注意的是为了实现深克隆我们需要借助Java的Serializable 接口标识本类可以被序列化。Person类中包含了基本类型的成员变量以及引用类型的成员变量BodyBody的定义如下
public class Body implements Serializable {private static final Long VERSION 1001L;private String sex;private String hand;public Body(String sex, String hand) {this.sex sex;this.hand hand;}public String getSex() {return sex;}public void setSex(String sex) {this.sex sex;}public String getHand() {return hand;}public void setHand(String hand) {this.hand hand;}Overridepublic String toString() {return Body{ sex sex \ , hand hand \ };}
}
为了能实现序列化Body类也要实现Serializable接口。当需要使用浅克隆的时候我们就通过Person对象的clone()方法来生成当需要使用深克隆的时候我们就使用deepClone()方法来生成。
最后就是使用对应的克隆方法生成克隆对象
public class Client {public static void main(String[] args) throws IOException, ClassNotFoundException {// 创建一个Person对象Person person new Person(walt, 18);// 创建出Body对象Body body new Body(男, 男生的手);person.setBody(body);System.out.println(原始的Person: person);// 使用浅克隆生成一个克隆对象Person clonePerson person.clone();System.out.println(克隆的Person: clonePerson);// 获取到克隆对象的Body并做修改Body cloneBody clonePerson.getBody();cloneBody.setSex(女);cloneBody.setHand(女生的手);clonePerson.setBody(cloneBody);// 分别打印出克隆的对象和原始对象System.out.println(克隆Person: clonePerson ,原始Person: person);// 检查克隆对象的body和原始对象的body是否是同一个是就为浅克隆不是为深克隆System.out.println(克隆的Body是否等于原始的Body: (body cloneBody));// 使用深克隆生成一个对象Person deepClonePerson person.deepClone();// 获取到深克隆后的person对象的body并修改Body deepCloneBody deepClonePerson.getBody();deepCloneBody.setSex(深克隆男孩子);deepCloneBody.setHand(深克隆男生的手手);deepClonePerson.setBody(deepCloneBody);// 打印出深克隆后的对象和原始的对象System.out.println(深克隆Person: deepClonePerson ,原始Person: person);// 检查克隆对象的body和原始对象的body是否是同一个是就为浅克隆不是为深克隆System.out.println(深克隆的Body是否等于原始的Body: (body deepCloneBody));}
}运行结果