2012-05-08 6 views
10

내 경험에 비추어 볼 때 자바와 같은 객체 지향 언어의 방문자 패턴, 전략 패턴 등과 같은 디자인 패턴을 자주 볼 수는 있지만 C와 같은 절차 언어에서 많은 패턴을 보지 못했습니다. 그 패턴이 절차 적 언어로 존재한다면?절차 언어에 디자인 패턴이 있습니까?

+2

질문에 대한 태그를 선택할 때주의하십시오. 태그는 * 아닙니다 * 키워드입니다. [tag : design] 및 [tag : patterns]로 질문에 태그를 지정해도 [tag : design-patterns]으로 태그를 지정하는 것과 같은 의미는 아닙니다. – Charles

+0

OOP를 절차 언어의 디자인 패턴으로 간주 할 수 있습니까? – savagent

+0

@savagent 그것은 당신이 디자인 패턴으로 생각하는 것에 달려 있습니다. 일반적으로 많은 다른 언어로 적용 할 수있는 일반적인 문제에 대한 재사용 가능한 솔루션으로 간주되어 언어 별 도구에 의존하지 않으므로 대부분의 OOP는 디자인 패턴이 아닙니다. 그러나 ANSI-C에서는 좋은 예를 들어 Schreiner의 저서 [ANSI-C가있는 OOP (https://www.cs.rit.edu/~ats/books/ooc.pdf)를 참조하십시오). 유용한 정의에 대해이 질문을 참조하십시오. http://stackoverflow.com/q/4787799/929395 – k3oy

답변

1

"디자인 패턴 : 재사용 가능한 객체 지향 소프트웨어의 요소"라는 책은 컴퓨터 프로그래밍, 디자인 및 아키텍처의 실천에 대한 디자인 패턴에주의를 기울이는 획기적인 책이었습니다. 당시 지배적 인 프로그래밍 패러다임은 객체 지향 소프트웨어 개발이었습니다. 그리고이 책은 분명히 다른 사람이 아니라 패러다임을 목표로 삼았습니다. 책의 디자인 패턴 중 일부가 다른 패러다임에 적용되었다고 주장 할 수도 있지만, 책의 초점은 아닙니다. 따라서 디자이너와 프로그래머에게 인기가있는 것은이 책에서 설명한 디자인 패턴 집합입니다. 그 이후 다른 사람들은 다른 저자, 블로거 및 다른 웹 사이트에서 문서화되었습니다. 여러 웹 사이트에서 설명 된 절차 언어에 적용되는 디자인 패턴이 있다는 것은 의심의 여지가 없습니다.하지만 내가 말했던 것처럼 프로그래밍 공동체가 디자인 패턴을 말할 때 주로 그 책에서 설명한 패턴을 참조합니다. 절차 적 언어에 대한 문서화 된 패턴이있는 곳이 없기 때문에 이것이 진정한 대답이 아니라는 것을 알고 있습니다. 확실합니다. 그 책의 중요성과 그것이 원래 목표로 삼고 있던 패러다임을 말할 수 있을지도 모른다고 생각했습니다.

17

실제로 절차 언어에는 디자인 패턴이 있습니다. 그러나 절차 적 접근법은 일반적으로 클래스 기반 OOP에 유리하게 무시되기 때문에 널리 인정되지 않는다.

고성능 소프트웨어를 C로 개발하고 몇 가지 되풀이 패턴이 있습니다. 그래서 나는 자주 보게되는 패턴에 대해 약간의 통찰력을 제공 할 것입니다.

이 캡슐화는 절차 적 프로그래밍을 수행하는 방법이다

를 처리합니다. 생성 함수는 구조체 또는 객체를 반환하지 않습니다. 그러나 핸들 : 일반적으로 불투명 한 포인터 또는 정수입니다. 단지 숫자 일 뿐이므로 아무 것도 흥미로울 수 없습니다. 세부 정보는 완전히 숨겨져 있습니다. 하지만 당신은 그것을 처리 기능이 핸들을 전달할 수 있습니다

예 :

  • Windows에서 CreateWindow 함수는 HWND를 반환합니다. ShowWindow, DestroyWindow 등과 같은 다른 함수로 전달 될 수있는 창 핸들입니다.
  • 리눅스에서는 open 시스템 호출입니다. 그냥 int를 반환합니다. 어떤 파일 핸들입니다.

컨텍스트

개체는 일반적으로 절차 적 언어로 상황이라고합니다. 컨텍스트는 객체의 멤버와 마찬가지로 일부 시스템의 상태를 포함하는 구조체입니다. OOP에서는 object.method(parameter)이라고 씁니다. 절차 적 프로그래밍에서는 function(addressOfContext, parameter)이라고 씁니다. 내부 함수는 컨텍스트 구조를 직접 사용하지만 public 함수는 핸들 만 처리하고 구현은이를 실제 컨텍스트 구조로 해석합니다.

콜백

또는 함수 포인터. 함수의 사용자는 자신의 함수 주소를 전달하여 사용자 정의 동작을 시스템에 추가합니다. 이것은 다형성이 절차 적 프로그래밍에서 어떻게 이루어 지는지를 보여줍니다. 이를 통해 일반 함수를 작성할 수 있습니다.

이 중 주목할만한 예로는 qsort C 함수가 있습니다. 이것은 요소 배열의 주소를 취합니다. 하나의 요소가 얼마나 큰지와 배열의 요소 수와 비교를 수행하는 비교 함수를 취합니다. 이것은 완전히 일반적인 구현이며 모든 종류의 데이터를 정렬 할 수 있습니다.

설정 구조체 함수가 많은 방법으로 매개 변수화 할 수

. 일반적으로 설치 구조가 사용됩니다. 사양에서는 이러한 구조체가 기본적으로 0으로 채워져 있고 관련 멤버 만 채워지는 경우가 종종 있습니다. 일부 구성원이 상호 배타적 인 경우 조합에 포함됩니다. 이러한 설치 구조체의 대표적인 예는 WinAPI의 WNDCLASS입니다.

가변 크기 데이터

음이 오히려 일반적인 디자인 패턴보다 C 패턴입니다. 때로는 객체가 임의의 크기의 바이너리 페이로드를 보유 할 수 있습니다. 이 패턴은 일반적으로 여러 유형의 데이터 청크를 포함 할 수있는 것보다 이진 파일에서 데이터를 읽을 때 발생합니다. 그 같은 구조체에 의해 이루어집니다.

typedef struct 
{ 
    int someData; 
    int otherData; 
    int nPayloadLength; 
    unsigned char payload[1]; 
} VariableSized; 

그리고 다음 코드에서

이 수행됩니다

VariableSized *vs = malloc(sizeof(VariableSized) + extraLength); 

이 할당 메모리는 가변 길이 페이로드를위한 공간을 허용 구조체보다 큰 이잖아. 그러면 누구의 5 번째 바이트에 예를 들어 액세스 할 수 있습니다. vs->payload[4].

free 호출에서 전체 개체를 해제 할 수 있다는 이점이 있습니다. 또한 메모리에 연속 블록이 있음을 보장합니다. 따라서 힙의 다른 어딘가에 해당 버퍼를 할당하는 것보다 캐시를 ​​더 잘 활용합니다. OOP 디자인 패턴의

절차 적 대응은

OOP 패턴 절차 언어의 이름에 호출되지 않습니다. 그래서 여기서만 추측 할 수 있습니다.

생성 패턴

  • 추상 공장 : 추상 공장은 일반적으로 싱글이다. 이 경우이 패턴은 전혀 사용되지 않고 조건부 컴파일이 대신 사용됩니다. 그렇지 않으면 생성 함수를 제공하는 구조체를 설정하십시오.
  • 빌더 : 설치 구조체가 사용됩니다.
  • 공장 초기화 : 생성시 콜백이 사용됩니다.
  • 지연 초기화 : C++ 정적 로컬 변수가이 용도로 사용됩니다. C에서는 성능에 영향을주지 않는 곳에서 if (!initialized) { initialize(); initialized = 1; } 패턴을 사용할 수 있습니다. 성능이 중요한 코드의 경우 지연로드가 전혀 사용되지 않습니다. 사용자는 컨텍스트를 초기화 할 위치를 찾아야합니다.
  • 프로토 타입 : 절차 적 세계에서는 단순히 핸들을 주식 개체로 반환합니다. 예를 들면 WinAPI의 GetStockObject 함수입니다.변경 가능한 오브젝트의 경우, 성능상의 이유로 종종 copy-on-write 메커니즘이 사용됩니다.
  • 싱글 톤 : 단순히 최상위 함수를 작성하고 전역 상태가 절대적으로 필요할 때 전역 변수를 사용하십시오.

구조 패턴

  • 어댑터 및 외관 : 기존에 다른 인터페이스 구축을위한 패턴. 단순히 새로운 기능이 이전 기능과 다른 기능을 호출합니다.
  • 브리지 : 구체적인 구현에 대한 콜백은 setup struct 형식으로 제공됩니다.
  • 복합체 : 작동해야하는 상위 노드의 핸들을 지정하는 최상위 함수가 사용됩니다.
  • 장식 자 : 꾸미기 동작은 콜백 형식으로 제공됩니다. 또는 하나의 이벤트 처리기 콜백은 다양한 메시지를 수신하고 처리할지 여부를 결정할 수있는 모든 가능한 장식에 제공됩니다 (예 : WinAPI의 창 프로 시저).
  • 플라이 웨이드 : 읽기 전용 이진 데이터가 구조체 및 배열로 압축되어 사용됩니다.
  • 프록시 : OOP와 거의 비슷하지만 클래스가 없습니다.

행동 패턴

  • 책임의 체인 : 배열 또는 루프에 의해 통과 콜백의 연결리스트. 사양은 콜백이 루프를 중단시키는 요청을 처리 한 것을 나타내는 방법을 설명합니다.
  • 명령 : 명령은 doundo 콜백을 포함하는 구조체입니다. 이러한 콜백은 일반적으로 작동 할 수있는 컨텍스트를 취합니다. 명령의 배열은 실행 취소를 수행하기 위해 유지됩니다.
  • 인터프리터 : 컴파일러/파서/인터프리터는 lex 및 yacc를 사용하여 작성되거나 생성됩니다.
  • 반복자 : 핸들이 사용됩니다. 그렇지 않으면 핸들이 사용됩니다. 성능상의 이유로 C에서는 종종 배열을 사용합니다.
  • 중재자 : 보통 메시지 디스패치 메커니즘 인 message loops과 이벤트 처리기를 사용하여 실현됩니다.
  • 메멘토 : OOP와 동일하지만 클래스가 없습니다.
  • 옵서버 : 책임 체인과 동일하지만 루프가 중단되지 않습니다. 예를 들면 atexit입니다.
  • 상태 : 현재 상태와 요청 된 작업을 함수로 매핑하는 2 차원 디스패치 테이블로 실현됩니다. (드문 경우지만 단순히 if가 사용됩니다.)
  • 전략 : 이것은 콜백의 기본 유스 케이스입니다.
  • 템플릿 메서드 : 일반적으로 프레임 워크를 사용하면 사용자가 일부 기능에 대해 자신의 콜백을 제공 할 수 있습니다. 라이브러리는 사용자 정의 메모리 할당 기능을 사용하여 사용자 정의 mallocfree을 제공하는 방법을 제공합니다.
  • 방문자 : 콜백의 다차원 배열을 사용하여 실현됩니다. 기본적으로 시작시 NULL로 채워지고 (기본 동작의 경우) 각 유형 쌍의 기본 초기화 코드에 채워집니다.
관련 문제