창설 형 디자인 모델 의 깊 은 복사 와 얕 은 복사 원형 모델
10946 단어 디자인 모드
프로 토 타 입 모드 (Prototype Pattern) 는 생 성 형 디자인 모델 중 하나 로 대상 을 직접 만 드 는 대가 가 클 때 기 존 대상 을 복제 하여 성능 원 가 를 절약 하 는 데 사용 된다.예 를 들 어 한 대상 이 높 은 대가 의 IO 나 데이터 베 이 스 를 방문 해 야 만 들 수 있 습 니 다. 이러한 경우 초기 화 는 매우 많은 자원 을 소화 해 야 합 니 다. 그러면 우 리 는 이미 만 든 대상 을 원형 으로 캐 시 할 수 있 습 니 다. 다음 에 똑 같은 이미지 가 필요 할 때 이 를 복제 할 수 있 습 니 다. 복제 과정 에서 원래 의 구조 방법 은 실행 되 지 않 습 니 다.프로 토 타 입 모델 은 따로 나타 나 지 않 고 공장 모델 과 협조 하 며 먼저 프로 토 타 입 대상 을 캐 시 초기 화 한 다음 에 공장 을 통 해 호출 자 에 게 제공 합 니 다.
2 실현
우리 가 공장 모델 을 사용 할 때 예 를 들 어 원형 모델 은 한 핸드폰 업 체 가 스마트 폰 과 스마트 시계 두 가지 하드웨어 제품 을 생산 해 야 한다 고 가정 한다. 그 중에서 핸드폰 과 시 계 는 대상 을 만 들 때 초기 화 비용 이 매우 높 기 때문에 원형 모델 의 형식 으로 이미 존재 하 는 원형 대상 을 복제 했다.
제품 류, 핸드폰 과 시 계 는 모두 하드웨어 에 속 하기 때문에 이들 을 추상 화 시 켜 야 한다. 하드웨어 추상 류 는 Cloneable 을 계승 하고 clone 방법 을 다시 써 야 한다.
public abstract class Hardware implements Cloneable {
protected int mId;
protected String mName;
@Override
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
public abstract void showInfo();
}
public class Phone extends Hardware {
public Phone(int id, String name) {
//
mId = id;
mName = name;
}
@Override
public void showInfo() {
System.out.println(" {" + mId + "," + mName + "} !");
}
}
public class Watch extends Hardware {
public Watch(int id, String name) {
//
mId = id;
mName = name;
}
@Override
public void showInfo() {
System.out.println(" {" + mId + "," + mName + "} !");
}
}
제품 공장 (제품 캐 시) 은 원형 을 미리 초기 화하 여 캐 시 하 는 데 사 용 됩 니 다. 새로운 대상 을 만 들 려 면 캐 시 대상 을 호출 하 는 clone 방법 으로 새로운 대상 을 복제 해 야 합 니 다.
public class HardwareFactory {
private static Map sHardwareMap = new HashMap<>();
public static Hardware createHardware(String hardwareName) {
Hardware hardware = sHardwareMap.get(hardwareName);
if (hardware == null) {
throw new UnsupportedOperationException(" ");
}
return (Hardware) hardware.clone();
}
public static void init() {
Hardware phone = new Phone(1, " 1 ");
sHardwareMap.put(" ", phone);
Hardware watch = new Watch(2, " 2 ");
sHardwareMap.put(" ", watch);
}
}
호출 자: 먼저 하드웨어 공장 에서 제품 대상 의 원형 을 초기 화하 고 나중에 createHardware 방법 으로 복 제 된 새로운 대상 을 직접 가 져 옵 니 다.
HardwareFactory.init();
Hardware phone = HardwareFactory.createHardware(" ");
phone.showInfo();
Hardware phone2 = HardwareFactory.createHardware(" ");
phone2.showInfo();
Hardware watch = HardwareFactory.createHardware(" ");
watch.showInfo();
Hardware watch2 = HardwareFactory.createHardware(" ");
watch2.showInfo();
출력 실행:
{1, 1 } !
{1, 1 } !
{2, 2 } !
{2, 2 } !
3 깊 은 복사 와 얕 은 복사
우 리 는 두 가지 개념, 얕 은 복사 와 깊 은 복사 등 을 이해한다.얕 은 복사 란 복사 대상 의 메모리 주소 입 니 다. 예 를 들 어 코드: obj A = obj B;그 중에서 이 두 개의 obj 는 어느 대상 의 속성 이 변화 하 더 라 도 다른 대상 에 게 영향 을 줄 수 있 습 니 다. 이 할당 과정 은 얕 은 복사 이 고 메모리 주소 만 복사 한 것 입 니 다. 즉, 실제 적 으로 같은 대상 을 가리 키 는 것 입 니 다.한편, 심 복 사 는 새로운 대상 을 만 드 는 것 으로 신 구 두 대상 은 그 중의 한 대상 의 변화 에 영향 을 주지 않 는 다.
그러면 우 리 는 상술 한 예 에서 얕 은 복사 입 니까? 깊 은 복사 입 니까?답 은 얕 은 복사 다.우 리 는 아래 에서 상술 한 제품 류 를 개선 하여 반 례 를 들 겠 다.
제품 종류: 이번 에는 하드웨어 추상 류 에 맵 과 사용자 정의 Cpu 류 를 추가 합 니 다.
public abstract class Hardware implements Cloneable {
protected int mId;
protected String mName;
protected Map mScore;
protected Cpu mCpu;
public void setId(int id) {
mId = id;
}
public int getId() {
return mId;
}
public void setName(String name) {
mName = name;
}
public void setScore(Map score) {
mScore = score;
}
public void setCpuType(String type) {
mCpu.setType(type);
}
@Override
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
public abstract void showInfo();
}
public class Phone extends Hardware {
public Phone(int id, String name, Map score, Cpu cpu) {
mId = id;
mName = name;
mScore = score;
mCpu = cpu;
}
@Override
public void showInfo() {
System.out.println(" {" + mId + "," + mName + "} , CPU:" + mCpu.getType() + ", :" + mScore);
}
}
public class Cpu {
private String mType;
public Cpu(String type) {
mType = type;
}
public void setType(String type) {
this.mType = type;
}
public String getType() {
return mType;
}
}
호출 자:
Map score = new HashMap<>();
score.put(" ", 999);
score.put(" ", 888);
Map score2 = new HashMap<>();
score2.put(" ", 100);
score2.put(" ", 200);
Phone phone1 = new Phone(1, " 1 ", score, new Cpu(" 865"));
phone1.showInfo();
Phone phone2 = (Phone)phone1.clone();
phone1.setId(2);
phone1.setName(" 2 ");
phone1.setScore(score2);
phone1.setCpuType(" 770");
phone2.showInfo();
출력 실행:
{1, 1 } , CPU: 865, :{ =999, =888}
{1, 1 } , CPU: 770, :{ =999, =888}
설명:
시범 을 보이 기 위해 서, 우 리 는 이번에 제품 공장 (제품 캐 시) 의 역할 을 생략 하고, 직접 호출 자 에 게 제품 대상 을 복제 하도록 했다.호출 자 중 먼저 phone 1 대상 을 원형 으로 만 든 다음 에 phone 2 대상 을 복제 한 다음 에 원형 phone 1 에 대해 4 가지 서로 다른 유형의 속성 을 수정 합 니 다. 각각 int, String, Map 과 사용자 정의 CPU 입 니 다.출력 매듭 을 보면 CPU 클래스 가 수 정 된 것 을 제외 하고 나머지 속성 은 원형 수정 으로 수정 되 지 않 았 습 니 다.
그 이 유 는 Cloneable 의 clone 방법 이 옅 은 복사 방법 을 제공 하기 때 문 입 니 다. 그리고 이 복사 방법 은 선택성 이 있 습 니 다. 예 를 들 어 기본 적 인 유형, 예 를 들 어 int, float, double 등 은 모두 그 값 을 복사 하 는 것 이 고 String, Integer, Float, Double 등 과 집합 은 인용 유형 이지 만 비교적 특수 한 것 도 그 값 을 복사 하 는 것 이 고 사용자 정의 유형 은 안 됩 니 다.주소 만 복사 해서 아이 폰 1 뒤에서 수정 하면 아이 폰 2 의 값 에 도 영향 을 줄 수 있 습 니 다.
3.1 딥 복사 개선 실현
제품 클래스 에서 인 용 된 클래스 도 Cloneable 에 계승 하고 clone 방법 을 실현 합 니 다.
public class Cpu implements Cloneable {
private String mType;
public Cpu(String type) {
mType = type;
}
public void setType(String type) {
this.mType = type;
}
public String getType() {
return mType;
}
@Override
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
제품 추상 클래스 의 clone 방법 에 대해 클래스 내 다른 사용자 정의 클래스 에 대한 복 제 를 추가 합 니 다. 여기에 코드 를 추가 합 니 다: mCpu = (Cpu) mCpu. clone ();
public abstract class Hardware implements Cloneable {
protected int mId;
protected String mName;
protected Map mScore;
protected Cpu mCpu;
public void setId(int id) {
mId = id;
}
public int getId() {
return mId;
}
public void setName(String name) {
mName = name;
}
public void setScore(Map score) {
mScore = score;
}
public void setCpuType(String type) {
mCpu.setType(type);
}
@Override
public Object clone() {
Object clone = null;
try {
clone = super.clone();
mCpu = (Cpu)mCpu.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
public abstract void showInfo();
}
수정 후 출력 실행:
{1, 1 } , CPU: 865, :{ =999, =888}
{1, 1 } , CPU: 865, :{ =999, =888}
3.2 Serializable 를 사용 하여 깊 은 복사 실현
위 에서 말 한 산 구 류 에서 인용 한 모든 종 류 를 Cloneable 을 계승 하여 clone 을 실현 하 는 것 외 에 serializable 인 터 페 이 스 를 사용 하여 바 이 너 리 흐름 의 직렬 화 를 읽 는 방식 으로 대상 의 깊 은 복 제 를 실현 할 수 있다.
제품 클래스 에서 인용 한 클래스 를 Serializable 로 직접 계승 하면 됩 니 다.
public class Cpu implements Serializable {
private String mType;
public Cpu(String type) {
mType = type;
}
public void setType(String type) {
this.mType = type;
}
public String getType() {
return mType;
}
}
제품 추상 류 에 대해 서도 Serializable 을 계승 하고 clone 방법 을 수정 합 니 다. 코드 는 다음 과 같 습 니 다.
public abstract class Hardware implements Cloneable, Serializable {
protected int mId;
protected String mName;
protected Map mScore;
protected Cpu mCpu;
public void setId(int id) {
mId = id;
}
public int getId() {
return mId;
}
public void setName(String name) {
mName = name;
}
public void setScore(Map score) {
mScore = score;
}
public void setCpuType(String type) {
mCpu.setType(type);
}
@Override
public Object clone() {
// Object clone = null;
// try {
// clone = super.clone();
// mCpu = (Cpu)mCpu.clone();
// } catch (CloneNotSupportedException e) {
// e.printStackTrace();
// }
// return clone;
Object clone = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
clone = objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return clone;
}
public abstract void showInfo();
}
수정 후 출력 실행:
{1, 1 } , CPU: 865, :{ =999, =888}
{1, 1 } , CPU: 865, :{ =999, =888}
총화
원형 모델 의 실현 원 리 는 매우 간단 하 다.성능 최 적 화 를 위해 생 겨 났 기 때문에 사용 장면 도 명확 하 다. 초기 화 류 의 원가 가 캐 시 기 존 대상 의 원형 보다 높 을 때 원형 모델 을 사용 하 는 것 을 권장 한 다 는 것 이다.사용 에 있어 서 주의해 야 할 것 은 복제 대상 일 때 원래 의 구조 방법 은 실행 되 지 않 을 것 이다. 또한 클래스 의 필드 가 깊 은 복사 에 만족 하 는 지 를 고려 하고 만족 하지 않 으 면 개선 을 지원 해 야 한다.지원 방식 은 인 용 된 클래스 도 Cloneable 인 터 페 이 스 를 계승 하여 clone 방법 을 실현 하거나 serializable 인 터 페 이 스 를 사용 하여 바 이 너 리 흐름 을 읽 고 직렬 화 하 는 방식 으로 대상 의 깊 은 복 제 를 실현 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
디자인 모델 의 공장 모델, 단일 모델자바 는 23 가지 디자인 모델 (프로 그래 밍 사상/프로 그래 밍 방식) 이 있 습 니 다. 공장 모드 하나의 공장 류 를 만들어 같은 인 터 페 이 스 를 실현 한 일부 종 류 를 인 스 턴 스 로 만 드 는 것...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.