23デザインパターンの深さを説明するために、デザインパターンであり、最終的に各平面の分析に努め。プロトタイプ - ADOは、第2の設計パターンを開始しました。
まず、なぜプロトタイプモデルを持っています
クラスがクローンに必要なとき、私たちは常に新しいオブジェクトをしたくない、その後、一つ一つは、属性値を設定します。今回は、の必要性を持っています
効率的なオブジェクトのコピー方法、プロトタイプデザインパターンが出現しました。
第二に、プロトタイプのデザインパターンの文言
プロトタイプデザインパターン:
パブリッククラスパーソン実装Cloneableを {
プライベート文字列のuserName;
プライベート文字列のセックス。
プライベートint型の年齢;
パブリック文字列getUserNameは(){
ユーザー名を返します。
}
公共ボイドsetUserName(文字列のuserName){
this.userName = userNameに。
}
パブリック文字列getSex(){
戻り性別;
}
公共ボイドsetSex(文字列性別){
this.sex =セックス。
}
公共INT getAge(){
戻り年齢;
}
公共ボイドsetAge(int型の年齢){
this.age =年齢。
}
@Override
保護された人のクローン()CloneNotSupportedException {スロー
人の人物=(人物)super.cloneを()。
人を返します。
}
@Override
公共の文字列のtoString(){
リターン"人{" +
"のuserName = '" + userNameに+ '\'' +
"性別= '" +性別+ '\'' +
」、年齢= "+年齢+
「}」。
}
}
公共の静的な無効メイン(文字列[]引数)はCloneNotSupportedException {スロー
人物P =新しい人を()。
p.setAge(19)。
p.setUserName( "小明");
p.setSex( "男");
人物P1 = p.clone()。
System.out.println(p.hashCode())。
System.out.println(p1.hashCode())。
p.setAge(12)。
System.out.println(P)。
System.out.println(P1)。
}
执行结果
プロトタイプの実装、Personクラス、実装Cloneableインタフェースとcloneメソッド缶をオーバーライドします。
増加は人では基本的なタイプではなく、また、プロパティの文字列型は、状況はあなたに事故を作ればすべてが、しかし、非常に素晴らしいと思われます。
1、シャローコピー
パブリッククラスパーソン実装Cloneableを{
プライベート文字列のuserName;
プライベート文字列のセックス。
プライベートint型の年齢;
民間の息子の息子。
公共の息子getSon(){
リターンの息子。
}
公共ボイドsetSon(SON息子){
this.son =息子。
}
パブリック文字列getUserNameは(){
ユーザー名を返します。
}
公共ボイドsetUserName(文字列のuserName){
this.userName = userNameに。
}
パブリック文字列getSex(){
戻り性別;
}
公共ボイドsetSex(文字列性別){
this.sex =セックス。
}
公共INT getAge(){
年齢を返します。
}
公共ボイドsetAge(int型の年齢){
this.age =年齢。
}
@Overrideは、
人のクローンを()CloneNotSupportedException {スロー保護された
人物の人物=(人物)super.cloneを()。
人を返します。
}
@Override
公共の文字列のtoString(){
リターン"人{" +
"のuserName = '" + userNameに+ '\'' +
"性別= '" +性別+ '\'' +
」、年齢= "+年齢+
"息子=" +息子+
'}';
}
}
パブリッククラス息子 {
プライベート文字列sonName。
パブリック文字列getSonName(){
sonNameを返します。
}
公共ボイドsetSonName(文字列sonName){
this.sonName = sonName。
}
@Override
パブリック文字列のtoString(){
リターン"息子{" +
"sonName = '" + sonName + '\'' +
'}'。
}
}
Testクラス{公共
メインボイドのpublic static(文字列[]引数){CloneNotSupportedExceptionスロー
人新しい新しいP =人を();
p.setAge(19);
p.setUserName( "ボブ");
p.setSex( "M")。
=新しい新しい息子息子息子();
son.setSonName( "暁明の子");
p.setSon(息子);
人物P1 = p.clone();
System.out.printlnは(p.hashCode());
システム。 out.printlnを(p1.hashCode());
p1.getSon()setSonName( "ファラオ子供隣");.
p1.setAge(12)
のSystem.out.println(P-);
System.out.printlnは( P1);
}
}
結果は以下の通りであります
では、なぜこのような結果が起こることができますか?
因为clone方法并不能穿透到son,也就是p和p1公用了son对象(p1对象对son的clone只是copy了指针,并没有完全copy,也就是浅拷贝),所以p和p1同时输出的“隔壁老王的孩子”。
如果我们希望实现完整的clone,该如何处理呢?我们需要深拷贝。
2,深拷贝
1)套娃式深拷贝
我们在浅拷贝的基础上修改,修改部分笔者用红色标识。
public class Person implements Cloneable {
private String userName;
private String sex;
private int age;
private Son son;
public Son getSon() {
return son;
}
public void setSon(Son son) {
this.son = son;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.setSon(person.getSon().clone());
return person;
}
@Override
public String toString() {
return "Person{" +
"userName='" + userName + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", son=" + son +
'}';
}
}
public class Son implements Cloneable {
private String sonName;
public String getSonName() {
return sonName;
}
public void setSonName(String sonName) {
this.sonName = sonName;
}
@Override
public String toString() {
return "Son{" +
"sonName='" + sonName + '\'' +
'}';
}
@Override
protected Son clone() throws CloneNotSupportedException {
return (Son) super.clone();
}
}
我们再来看结果:
很显然,得到了我们期望的结果,像不像套娃?
2)序列化深拷贝
首先改造Person
public class Person implements Serializable {
private String userName;
private String sex;
private int age;
private Son son;
public Son getSon() {
return son;
}
public void setSon(Son son) {
this.son = son;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"userName='" + userName + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", son=" + son +
'}';
}
}
接着,改造Son
public class Son implements Serializable {
private String sonName;
public String getSonName() {
return sonName;
}
public void setSonName(String sonName) {
this.sonName = sonName;
}
@Override
public String toString() {
return "Son{" +
"sonName='" + sonName + '\'' +
'}';
}
}
Main方法
public class Test {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Person p = new Person();
p.setAge(19);
p.setUserName("小明");
p.setSex("男");
Son son = new Son();
son.setSonName("小明的孩子");
p.setSon(son);
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(p);
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
Person p1= (Person) ois.readObject();
System.out.println(p.hashCode());
System.out.println(p1.hashCode());
p1.getSon().setSonName("隔壁老王的孩子");
p1.setAge(12);
System.out.println(p);
System.out.println(p1);
}
}
来看看输出结果:
很显然,得到了我们期望的结果。
当然,可以把序列化过程封装到Person中。没有了套娃,又可以欢乐玩耍了。
总结:每一种拷贝都有自己的应用场景,要看具体的业务场景。