2010-12-19 6 views
2

학습 목적으로 소켓 기반 클라이언트/서버 응용 프로그램을 작성하고 있습니다. 나는 패킷을 올바르게 처리 할 수 ​​있도록 사용자 정의 프로토콜을 설계했다. 오늘날 코드의 일부 오래된 부분을 검사하면서 데이터 패킷을 만드는 내 방식에 많은 중복 코드가 포함되어 있다는 것을 깨달았습니다.어떤 디자인 패턴을 사용해야합니까?

나는 다른 종류의 패킷을 가지고 있습니다. ImagePacket, MessagePacket 등 모든 유형의 생성은 사소한 일에만 다르다. 예를 들어, 헤더와 구분자 생성은 동일하다.

이를 개선하기 위해, 난 (간체)과 같은 솔루션을 내놓았다 :

abstract class Packet 
{ 
public Packet(object o) 
{ 
MemoryStream memoryStream = new MemoryStream();   

AddHeader(ref memoryStream); 
AddData(ref memoryStream, obj); 
AddDelimiter(ref memoryStream); 
_packetBytes = memoryStream.ToArray(); 

memoryStream.Close(); 
} 
protected abstract void AddData(ref MemoryStream ms, object obj); 

는, addData 방법은 추상적 인 방법으로 구현 추상에 정의되어 AddHeader 및 AddDelimiter 반면 구체적인 클래스에서 재정의한다 클래스 패킷 그 자체.

잘 작동하고 이전과 많이 중복 된 코드가 없지만 AddData에 개체를 전달하는 것이 만족스럽지 않습니다. ImagePacket 생성자에 문자열을 지정하면 안된다는 것이 명확하지 않기 때문입니다.

// correct 
Packet myMsgPacket = new MessagePacket("hello world"); 
Packet myImagePacket = new ImagePacket(image); 
// wrong, but will be compiled :(
Packet myChaosPacket = new ImagePacket("muaha you're doomed"); 

정확한 데이터 형식이 전달되었는지 확인해야한다면 엄청난 양의 코드가 다시 나옵니다. 어떻게하면 중복 된 코드를 줄일 수 있지만 위에서 언급 한 문제를 없앨 수 있습니까?를 아래의 코멘트 당으로서 나는 명확 봤는데한다 : 당신이

Packet MyPacket = MyPacketFactory.CreatePacket(Data) 

MyFactory.CreatePacket

은 다음 IPacket

업데이트를 반환 공장 패턴을 사용할 필요가 같은

답변

3

이 울립니다. 귀하의 공장 ...

IPacket CreatePacket(Image Data) {} 
IPacket CreatePacket(String Data) {} 
IPacket CreatePacket(Exception Data) {} 

오버로드 CreatePacket() 다른 데이터 유형을 메소드를 가질 수 있습니다 당신은 단지 문자열 (예 : 메시지 패킷, 상태 패킷 또는 유사한)를 포함하는 패킷의 여러 유형이있는 경우를 예를 들어 AddDelimiter() - - 당신 내부 패킷 공장을 문자열 패킷이 요구되는 나타내는 열거 ...

IPacket CreatePacket(String Data, StringPacketTypesEnum PacketType) {} 

를 만들 수 있습니다, 당신은 일반적인 모든 코드가 중복 처리 기능을 가질 수이 코드를 유지합니다 DRY

+0

질문은 Data 매개 변수가 될 수있는 것입니다. 사용자는 Data가 문자열인지 이미지인지 알기를 원합니다. –

+0

아마도 내가 분명히해야하지만 당연히 할 수 있습니다 - 나는 다른 데이터 형식과 아마도 문자열 데이터에 대한 추가'enum' 유형을 사용하는 많은 오버로드를 가질 수 있습니다 – Basic

0

Ruby on Rails는이를 해결하기 위해 유효성 검사를 사용합니다.

addData() 함수가 입력에 validate()를 호출하면 각 하위 클래스에서 validate()를 재정의해야합니다.

0

인터페이스를 반환하는 팩터 리 패턴으로 이동합니다.

그 외에도 참조 유형에는 참조를 사용할 필요가 없습니다.

0

현재 해결책이 괜찮다고 생각합니다. ImagePacket 생성자에 전달 된 데이터 유형을 Image 유형으로 한정하면됩니다.예를 들면 다음과 같습니다.

class ImagePacket : Packet{ 
    public ImagePacket(Image img) : base(img){} 
} 

이렇게하면 데이터가 복사 할 때 이미지인지 확인할 수 있습니다. 물론, 실제로 object 유형을 전달해야하는 경우에는 작동하지 않을 수 있습니다.

관련 문제