2008-09-30 2 views
10

알고리즘을 클래스에 캡슐화하는 것이 얼마나 일반적인 것인지 궁금합니다. 보다 구체적으로, 대신 서로간에 공통 매개 변수를 전달하는 별도의 기능을 수있는의 :알고리즘을 클래스로 캡슐화하기

void f(int common1, int param1, int *out1); 
void g(int common1, int common2, int param1, int *out2) 
{ 
    f(common1, param1, ..); 
} 

클래스에 공통 매개 변수를 캡슐화하고 생성자에서 모든 작업을 수행합니다

struct Algo 
{ 
    int common1; 
    int common2; 

    Algo(int common1, int common2, int param) 
    { // do most of the work } 

    void f(int param1, int *out1); 
    void g(int param1, int *out2); 
}; 

을 함수 인수를 통해 일반적인 매개 변수와 중간 결과를 전달하지 않아도되는 것은 매우 실용적인 것처럼 보입니다. 그러나이 "패턴"이 널리 사용되는 것을 보지 못했습니다. 가능한 단점은 무엇입니까?

답변

5

그것은 전혀 나쁜 전략이 아니다 :

나는 보통

class MyFunctor { 
    public: 
     MyFunctor(/* List of Parameters */); 
     bool execute(); 
    private: 
     /* Local storage for parameters and intermediary data structures */ 
} 

가 그럼 난 내 펑터이 방법을 사용하여 다음과 같은 템플릿을 사용하십시오. 사실, 당신이 당신의 언어 (당신이 C++에서 할 수있는 능력)가 기본 기능에 대한 불투명 한 인터페이스를 정의하는 어떤 종류의 추상 수퍼 클래스를 정의한다면, 런타임시 다른 알고리즘을 안팎으로 바꿀 수 있습니다 (정렬 알고리즘, 예를 들어). 선택한 언어에 리플렉션이있는 경우 무한히 확장 할 수있는 코드가 있어도 알고리즘을 사용하는 소비자가있을 때 존재하지도 않은 알고리즘을로드하고 사용할 수 있습니다. 또한 다른 기능 클래스와 알고리즘 클래스를 느슨하게 결합 할 수 있으므로 리팩토링에 도움이되고 대규모 프로젝트에서 작업 할 때 온전한 정신을 유지할 수 있습니다.

물론 복잡한 클래스 구조를 빌드하기 시작할 때마다 빌드 및 유지 관리해야 할 추가 아키텍처 및 코드가 생성됩니다. 그러나, 내 의견으로는 장기간에이 이득은이 작은 불편보다 중요합니다.

마지막 제안 하나 : 하지 마십시오 생성자에서 작업하십시오. 생성자는 클래스 내부 구조를 적당한 기본값으로 초기화하는 데에만 사용해야합니다. 예, 초기화를 완료하는 다른 메소드 호출을 포함 할 수 있지만 초기화는 이 아니며 조작입니다. 찾고 있던 특정 알고리즘을 실행하기 위해 코드에서 한 번 더 호출해야하는 경우에도 두 개가 별도로 존재해야합니다.

0

생성자 매개 변수를 사용하여 두 메서드를 모두 호출해야하는 경우이를 수행합니다.

동일한 매개 변수를 사용하여 두 메서드를 모두 호출 할 필요가 없다면 그렇게하지 않을 것입니다.

5

문제를 해결하는 디자인 패턴이 있습니다. 그것은 "Strategy Design Pattern"이라고 불리우며 그것에 대한 좋은 정보를 찾을 수 있습니다 here.

"전략"에 대한 좋은 점은 알고리즘을 사용하는 클라이언트를 수정하지 않고도 알고리즘 패밀리를 정의한 다음이를 상호 교환하여 사용할 수 있다는 점입니다.

1

보통 알고리즘을 캡슐화하기 위해 펑터 또는 Function Object을 만듭니다.

bool success = MyFunctor(/*Parameter*/).execute(); 
+0

operator()를 사용하여 함수 객체가 실행되기를 기대합니다. –

1

아마도 더 나은 방법은 (뭔가를 놓치지 않는 한) 클래스의 알고리즘을 ecapsualte하고 메소드 호출을 통해 실행하도록하는 것입니다.생성자를 통해 모든 매개 변수를 공용 속성에 전달하거나 알고리즘이 포함 된 클래스에 전달되는 모든 매개 변수를 캡슐화하는 구조체를 만들 수 있습니다. 그러나 일반적으로 그러한 생성자에서 물건을 실행하는 것은 좋은 생각이 아닙니다. 무엇보다도 직관적이지 않기 때문에.

public class MyFooConfigurator 
{ 
    public MyFooConfigurator(string Param1, int, Param2) //Etc... 
    { 
     //Set all the internal properties here 
     //Another option would also be to expose public properties that the user could 
     //set from outside, or you could create a struct that ecapsulates all the 
     //parameters. 
     _Param1 = Param1; //etc... 
    } 

    Public ConfigureFoo() 
    { 
     If(!FooIsConfigured) 
      return; 
     Else 
      //Process algorithm here. 
    } 
} 
2

은 귀하의 질문은 더 일반적으로, 같은 말로 표현 할 수 없습니다 "소프트웨어의 주요 아이디어는 단지 알고리즘을 실행 중일 때 우리가 어떻게 객체 지향 설계를 사용합니까?"

그런 경우에 나는 제안한 디자인이 좋은 첫 걸음이라고 생각하지만,이 문제는 종종 문제에 따라 다릅니다.

좋은 일반적인 디자인은 당신이 가진 것과 같다고 생각합니다. . .

class InputData {}; 
class OutputData {}; 

class TheAlgorithm 
{ 
private: 
    //functions and common data 

public: 
    TheAlgorithm(InputData);  
    //other functions 
    Run(); 
    ReturnOutputData(); 
}; 

그런 다음 원하는대로 main() 또는 GUI와 상호 작용하도록하십시오.

관련 문제