잠시 생각해 봅시다. 나는 당신이 2 개의 서브 클래스를 가지고있을뿐만 아니라, 이것을 일반화하자.
가장 먼저 떠오르는 것은 코드 복제, 확장 성 및 친밀 성입니다. 다음을 확장 해 봅시다 :
더 많은 클래스를 추가하려면 가능한 한 최소한의 코드를 변경해야합니다.
intersect
작업이 교환 법칙이 성립, 자신이 밖으로 질문 클래스 내부의 논리를 B
및 A
교차의 코드와 같은 장소에 있어야 A
및 B
교차, 그래서 유지하기위한 코드이기 때문입니다.
또한 새로운 클래스를 추가한다고해서 기존 클래스를 수정해야하는 것이 아니라 위임 클래스를 확장해야한다는 것을 의미합니다 (예, 여기에 패턴이 있습니다).
이 현재 구조, 나는 가정 (또는 intersect
비슷한, 아마 반환 유형,하지만 지금은 중요하지 않음) :
struct Primitive
{
virtual void intersect(Primitive* other) = 0;
};
struct Sphere : Primitive
{
virtual void intersect(Primitive* other)
};
struct Plane : Primitive
{
virtual void intersect(Primitive* other);
};
우리는 이미 우리가 Plane
내부의 교차 로직을하지 않으 결정 또는 Sphere
, 그래서 우리는 새로운 class
를 만들 :
struct Intersect
{
static void intersect(const Sphere&, const Plane&);
//this again with the parameters inversed, which just takes this
static void intersect(const Sphere&, const Sphere&);
static void intersect(const Plane&, const Plane&);
};
이 당신이 새로운 기능을 추가 할 예정 클래스, 새로운 논리이다. 예를 들어 Line
클래스를 추가하려는 경우 intersec(const Line&,...)
메서드를 추가하기 만하면됩니다.
새 클래스를 추가 할 때 기존 코드를 변경하고 싶지 않습니다. 따라서 교차 함수 내부의 유형을 확인할 수 없습니다.
우리는 종류에 따라 다르게 작동이 (전략 패턴)을위한 행동 클래스를 만들 수 있습니다, 우리는 나중에 확장 할 수
struct IntersectBehavior
{
Primitive* object;
virtual void doIntersect(Primitive* other) = 0;
};
struct SphereIntersectBehavior : IntersectBehavior
{
virtual void doIntersect(Primitive* other)
{
//we already know object is a Sphere
Sphere& obj1 = (Sphere&)*object;
if (dynamic_cast<Sphere*>(other))
return Intersect::intersect(obj1, (Sphere&) *other);
if (dynamic_cast<Plane*>(other))
return Intersect::intersect(obj1, (Plane&) *other);
//finally, if no conditions were met, call intersect on other
return other->intersect(object);
}
};
그리고 우리의 원래의 방법에
우리는 거라고 :
을
struct Sphere : Primitive
{
virtual void intersect(Primitive* other)
{
IntersectBehavior* intersectBehavior = BehaviorFactory::getBehavior(this);
return intersectBehavior.doIntersect(other);
}
};
:
struct Sphere : Primitive
{
virtual void intersect(Primitive* other)
{
SphereIntersectBehavior intersectBehavior;
return intersectBehavior.doIntersect(other);
}
};
이보다 청소기 디자인은 동작 중 추상적 실제 유형, 팩토리를 구현하는 것
그리고 심지어 모든 클래스에 대해 이렇게하기 때문에 intersect
이 가상 일 필요는 없습니다. 새로운 클래스를 추가 할 때이 디자인
- 에게 기존 코드를 수정할 필요를 따라하지 않는 경우
- 는
- 는 각각의 새로운 유형
- 만
IntersectBehavior
을 확장 한 곳에서 구현이 새로운 유형의 경우 Intersect
클래스에서 구현을 제공하십시오.
그리고 이것이 더 완벽해질 수있을 것입니다.
다형성을 원하는 경우 왜 정적 유형을 원하겠습니까? 인터페이스에서 기본 클래스 포인터를 사용하고 런타임에 유형을 동적으로 파악하도록하십시오. 가상 메서드에 대한 전체적인 점이 있습니다. – AJG85
어떻게 가상 정적이라고 부릅니까? –
[http://stackoverflow.com/questions/325555/c-static-member-method-call-on-class-instance] 또는 'this' 포인터를 통해서도 인스턴스를 호출 할 생각이었습니다. , 예. [http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr039.htm] – wsaleem