C \ # 디자인 모델 의 6 - 원형 모델
목표 류 는 하나 이상 의 원형 류 를 복제 하여 구 조 를 한 다음 에 복 제 된 클래스 의 세부 사항 을 수정 하거나 채 워 서 그 행 위 를 미리 기대 에 부합 하도록 한다.프로 토 타 입 모드 는 일반적으로 부모 데이터 에 대한 클론 문 제 를 설계 합 니 다.
일반적인 상황 에서 하나의 클래스 가 하나의 배열 구성원 을 포함 하고 이 클래스 가 ICloneable 인 터 페 이 스 를 실현 한다 면 이 클래스 는 Clone () 방법 으로 복 제 를 할 수 있 지만 복제 가 우리 의 요구 에 부합 되 는 지 는 확실 하지 않다.
object Clone(); 복제 방법 은 object 류 를 되 돌려 줍 니 다.
만약 에 배열 을 포함 하 는 인 스 턴 스 가 복제 된다 면 새로운 인 스 턴 스 의 배열 이 원래 배열 의 인용 일 뿐 이 라면 얕 은 복사 (shallow copy) 라 고 합 니 다. 데이터 대상 의 인용 은 복사 되 었 지만 똑 같은 바닥 데 이 터 를 가리 키 고 있 습 니 다.모든 복사 본 에서 실 행 된 작업 은 원래 인 스 턴 스 의 데 이 터 를 바 꿉 니 다. 어떤 경우 에는 우리 가 원 하 는 결과 가 아 닙 니 다.
그래서 우 리 는 깊이 복사 하여 새로운 데이터 실 체 를 완전히 구축 할 수 있다.
public object Clone() {
//create a new ArrayList
ArrayList swd = new ArrayList ();
//copy in swimmer objects
for(int i=0; i< swdata.Count ; i++)
swd.Add (swdata[i]);
//create new SwimData object with this array
SexSwimData newsd = new SexSwimData (swd);
return newsd;
}
언제든지 클래스 가 생 성 될 수 있 거나 클래스 가 생 성 된 후에 수 정 될 때 원형 모드 를 사용 할 수 있 습 니 다.모든 종류 가 같은 인터페이스 만 있다 면 그들 은 실제로 상당히 다른 조작 을 할 수 있다.
우 리 는 Swimmer 류 가 하나 있다.
using System;
using CsharpPats;
namespace DeepSexClone
{
/// <summary>
/// Summary description for Swimmer.
/// </summary>
public class Swimmer:IComparable {
private string name; //name
private string lname, frname;//split names
private int age; //age
private string club; //club initials
private float time; //time achieved
private bool female; //sex
//---------
public Swimmer(string line) {
StringTokenizer tok = new StringTokenizer(line,",");
splitName(tok);
age = Convert.ToInt32 (tok.nextToken());
club = tok.nextToken();
time = Convert.ToSingle (tok.nextToken());
string sx = tok.nextToken().ToUpper ().Trim ();
female = sx.Equals ("F");
}
//---------
private void splitName(StringTokenizer tok) {
name = tok.nextToken();
int i = name.IndexOf (" ");
if (i > 0 ) {
frname = name.Substring (0, i);
lname = name.Substring (i + 1).Trim ();
}
}
//---------
public int CompareTo(object swo) {
Swimmer sw = (Swimmer)swo;
return lname.CompareTo (sw.getLName() );
}
//---------
public bool isFemale() {
return female;
}
//---------
public int getAge() {
return age;
}
//---------
public float getTime() {
return time;
}
//---------
public string getName() {
return name;
}
//---------
public string getClub() {
return club;
}
//---------
public string getLName() {
return lname;
}
}
}
수영 선수 정 보 를 포함 하 는 SwimData 클래스:
using System;
using System.Collections ;
using CsharpPats;
namespace DeepSexClone
{
/// <summary>
/// Summary description for SwimData.
/// </summary>
public class SwimData:ICloneable {
protected ArrayList swdata;
private int index;
//-----
public SwimData() {
swdata = new ArrayList ();
}
//-----
public SwimData(ArrayList swd) {
swdata = swd;
index=0;
}
//-----
public int count() {
return swdata.Count ;
}
//-----
public SwimData(string filename) {
swdata = new ArrayList ();
csFile fl = new csFile(filename);
fl.OpenForRead ();
string s = fl.readLine ();
while(s != null) {
Swimmer sw = new Swimmer(s);
swdata.Add (sw);
s = fl.readLine ();
}
fl.close ();
}
//-----
public object Clone() {
//create a new ArrayList
ArrayList swd = new ArrayList ();
//copy in swimmer objects
for(int i=0; i< swdata.Count ; i++)
swd.Add (swdata[i]);
//create new SwimData object with this array
SwimData newsd = new SwimData (swd);
return newsd;
}
//-----
public void moveFirst() {
index = 0;
}
//-----
public bool hasMoreElements() {
return (index < swdata.Count-1 );
}
//-----
public void sort() {
//sort using IComparable interface of Swimmer
swdata.Sort (0, swdata.Count , null);
}
//-----
public Swimmer getSwimmer() {
if(index < swdata.Count )
return (Swimmer)swdata[index++];
else
return null;
}
}
}
우 리 는 SwimData 류 를 계승 하 는 부류 가 있 는데, 이러한 SwimData 류 를 계승 하 는 자 류 는 부류 중의 수영 선수 들 의 정 보 를 복제 해 야 한다.저 희 는 SexsumData 류 가 SwimData 류 를 계승 하고 이런 유형 은 수영 선수 에 대한 정렬 방법 이 있 습 니 다. 그리고 SexsumData 류 는 자신의 Clone () 방법 이 필요 합 니 다. 서로 다른 데이터 형식 으로 돌아 가 야 하기 때문에 이런 유형 에서 부모 류 의 Clone () 방법 을 다시 써 야 합 니 다.
public object Clone() {
//create a new ArrayList
ArrayList swd = new ArrayList ();
//copy in swimmer objects
for(int i=0; i< swdata.Count ; i++)
swd.Add (swdata[i]);
//create new SwimData object with this array
SexSwimData newsd = new SexSwimData (swd);
return newsd;
}
이렇게 해서 매번 새로운 SwimData 클래스 의 하위 클래스 가 실 현 될 때마다 부모 클래스 의 Clone () 방법 을 다시 써 야 한다. 돌아 올 데이터 가 다 르 기 때문에 이것 은 매우 좋 지 않 은 방법 이다.더 좋 은 실현 방안 은 Clone () 방법 이 있 는 모든 클래스 에서 ICloneable 인터페이스의 제한 을 취소 하고 반전 처리 과정 을 통 해 모든 수신 류 가 전송 류 내부 의 데 이 터 를 복제 하 는 것 이다.
이렇게 해서 SwimData 류 의 변경 은 다음 과 같다.
public virtual void cloneMe(SwimData swdat) {
swdata = new ArrayList ();
ArrayList swd=swdat.getData ();
//copy in swimmer objects
for(int i=0; i < swd.Count ; i++)
swdata.Add (swd[i]);
}
Clone () 함 수 를 취소 하고 ICloneable 인터페이스 에 대한 실현 을 취소 하 며 위의 함수 cloneMe () 를 사용 합 니 다.
이 방법 은 SwimData 의 모든 하위 클래스 에 사용 할 수 있 습 니 다. 하위 클래스 간 에 데이터 의 강제 형식 전환 이 필요 하지 않 기 때 문 입 니 다.모든 하위 클래스 는 같은 데 이 터 를 가지 고 있다.
예 를 들 어 수영 선수 정보 에 따라 나이 분포 주 상 도 를 그 려 보 자.
AgeSwimData 클래스 는 SwimData 클래스 에서 계 승 됩 니 다.
using System;
using System.Collections ;
namespace DeepSexClone
{
/// <summary>
/// Summary description for SexSwimData.
/// </summary>
public class AgeSwimData:SwimData
{
ArrayList swd;
public AgeSwimData() {
swdata = new ArrayList ();
}
//------
public AgeSwimData(string filename):base(filename){}
public AgeSwimData(ArrayList ssd):base(ssd){}
//------
public override void cloneMe(SwimData swdat) {
swd = swdat.getData ();
}
//------
public override void sort() {
Swimmer[] sws = new Swimmer[swd.Count ];
//copy in swimmer objects
for(int i=0; i < swd.Count ; i++) {
sws[i] = (Swimmer)swd[i];
}
//sort into increasing order
for( int i=0; i< sws.Length ; i++) {
for (int j = i; j< sws.Length ; j++) {
if (sws[i].getAge ()>sws[j].getAge ()) {
Swimmer sw = sws[i];
sws[i]=sws[j];
sws[j]=sw;
}
}
}
int age = sws[0].getAge ();
int agecount = 0;
int k = 0;
swdata = new ArrayList ();
bool quit = false;
while( k < sws.Length && ! quit ) {
while(sws[k].getAge() ==age && ! quit) {
agecount++;
if(k < sws.Length -1)
k++;
else
quit= true;
}
//create a new Swimmer with a series of X's for a name
//for each new age
string name = "";
for(int j = 0; j < agecount; j++)
name +="X";
Swimmer sw = new Swimmer(age.ToString() + " " +
name + "," + age.ToString() + ",club,0,F");
swdata.Add (sw);
agecount = 0;
if(quit)
age = 0;
else
age = sws[k].getAge ();
}
}
}
}
AgeSwimData 의 cloneMe () 방법 은 들 어 오 는 데이터 에 대한 인용 형식 을 되 돌려 주 고 깊이 복사 하지 않 았 습 니 다.그러나 sort 방법 에 서 는 한 선수 의 정 보 를 저장 하 는 새로운 복사 본 을 만 들 고 이 선수 의 배열 을 정렬 하여 데 이 터 를 변경 하지 않 았 습 니 다.
private void btClone_Click(object sender, System.EventArgs e) {
AgeSwimData newSd = new AgeSwimData ();
newSd.cloneMe (swdata);
newSd.sort ();
lsNewKids.Items.Clear() ;
while(newSd.hasMoreElements() ) {
Swimmer sw = (Swimmer)newSd.getSwimmer ();
lsNewKids.Items.Add (sw.getName() );
}
}
이렇게 메 인 프로그램 에 AgeSwimData 의 인 스 턴 스 를 새로 만 들 었 습 니 다. 이 인 스 턴 스 는 정렬 할 때 원래 들 어 온 인 스 턴 스 데이터 가 아 닙 니 다.
프로 토 타 입 모델 의 가장 큰 장점 은 어떤 하위 클래스 로 돌아 가 든 이 종 류 를 새로운 유형 으로 바 꾸 지 않 아 도 프로그램 에서 사용 할 수 있다 는 것 이다. 부모 등급 의 추상 류 나 기본 적 인 방법 은 충분히 사용 해 야 한다. 클 라 이언 트 는 현재 처리 하고 있 는 것 이 진정한 하위 클래스 의 어떤 종류 인지 알 필요 가 없다.
새로운 인 스 턴 스 를 만 드 는 데 더 많은 대가 가 필요 할 때 프로 토 타 입 모드 는 새로운 인 스 턴 스 를 만 드 는 것 이 아니 라 기 존 클래스 를 복사 하거나 복제 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
디자인 모델 의 공장 모델, 단일 모델자바 는 23 가지 디자인 모델 (프로 그래 밍 사상/프로 그래 밍 방식) 이 있 습 니 다. 공장 모드 하나의 공장 류 를 만들어 같은 인 터 페 이 스 를 실현 한 일부 종 류 를 인 스 턴 스 로 만 드 는 것...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.