많은 사람들이 Singleton 패턴에 여러 가지 단점이 있으며 일부는 패턴을 완전히 피할 것을 제안한다는 데 동의하는 것 같습니다. 여기에 훌륭한 토론이 있습니다 . Singleton 패턴에 대한 의견을 해당 질문으로 보내주십시오.
내 질문 : 피하거나 세심한주의를 기울여 사용해야하는 다른 디자인 패턴이 있습니까?
많은 사람들이 Singleton 패턴에 여러 가지 단점이 있으며 일부는 패턴을 완전히 피할 것을 제안한다는 데 동의하는 것 같습니다. 여기에 훌륭한 토론이 있습니다 . Singleton 패턴에 대한 의견을 해당 질문으로 보내주십시오.
내 질문 : 피하거나 세심한주의를 기울여 사용해야하는 다른 디자인 패턴이 있습니까?
답변:
모든 디자인 패턴은주의해서 사용해야합니다. 제 생각 에는 패턴을 즉시 구현하는 대신 타당한 이유가있을 때 패턴을 리팩토링해야합니다 . 패턴 사용의 일반적인 문제는 복잡성을 추가한다는 것입니다. 패턴을 과도하게 사용하면 특정 응용 프로그램이나 시스템을 추가로 개발하고 유지 관리하기가 번거로워집니다.
대부분의 경우 간단한 솔루션이 있으며 특정 패턴을 적용 할 필요가 없습니다. 경험상 좋은 규칙은 코드 조각이 대체되거나 자주 변경되어야 할 때마다 패턴을 사용하고 패턴을 사용할 때 복잡한 코드에 대한주의를 기울일 준비를하는 것입니다.
기억 당신의 목표는 단순해야 하고 당신이 당신의 코드에서 지원 변화에 대한 실제적인 필요를 볼 경우 패턴을 사용합니다.
패턴이 과도하게 엔지니어링되고 복잡한 솔루션으로 이어질 수 있다면 패턴을 사용하는 것이 문제처럼 보일 수 있습니다. 그러나 프로그래머가 대부분의 패턴에 대한 토대가되는 디자인 기술과 원칙 을 읽는 것이 훨씬 더 흥미 롭습니다 . 실제로 내가 가장 좋아하는 '디자인 패턴'책 중 하나는 문제의 패턴에 적용 할 수있는 원칙을 반복함으로써이를 강조합니다. 관련성 측면에서 패턴보다 유용 할 정도로 간단합니다. 일부 원칙은 코드 모듈을 빌드 할 수있는 한 Liskov Substitution Principle 과 같은 객체 지향 프로그래밍 (OOP) 이상을 포함하기에 충분히 일반적 입니다.
다양한 디자인 원칙이 있지만 GoF 책 의 첫 번째 장에 설명 된 내용은 시작하기에 매우 유용합니다.
잠시 동안 당신에게 가라 앉게하십시오. GoF가 작성되었을 때 인터페이스 는 추상화 (슈퍼 클래스를 의미하기도 함)를 의미하며 Java 또는 C #의 유형 인 인터페이스와 혼동해서는 안됩니다. 두 번째 원칙은 오늘날에도 여전히 흔히 볼 수 있는 상속의 남용에서 비롯됩니다 .
여기에서 Robert Cecil Martin (일명 Bob 삼촌) 이 알려준 SOLID 원칙 을 읽을 수 있습니다 . Scott Hanselman 은 이러한 원칙 에 대한 팟 캐스트 에서 Bob 삼촌을 인터뷰했습니다 .
이러한 원칙은 동료들과 함께 읽고 토론하기에 좋은 출발점이됩니다. 원칙이 서로, 그리고 관심사 분리 및 종속성 주입 과 같은 다른 프로세스와 얽혀 있음을 알 수 있습니다 . TDD 를 한동안 수행 한 후에 는 분리 되고 반복 가능한 단위 테스트 를 생성하기 위해 어느 정도 따라야하기 때문에 이러한 원칙이 실제로 실제로 온다는 것을 알 수 있습니다 .
Design Patterns의 저자가 가장 걱정하는 것은 "Visitor"패턴이었습니다.
그것은 "필요한 악"이지만 종종 과도하게 사용되며 그 필요성은 종종 디자인에 더 근본적인 결함을 드러냅니다.
"Visitor"패턴의 대체 이름은 "Multi-dispatch"입니다. 방문자 패턴은 단일 유형의 디스패치 OO 언어를 사용하여 두 유형을 기반으로 사용할 코드를 선택하려는 경우에 끝나는 것이기 때문입니다. (또는 그 이상) 다른 개체.
고전적인 예는 두 모양 사이에 교차점이 있지만 종종 간과되는 훨씬 더 간단한 경우가 있습니다. 두 이기종 개체의 동등성을 비교하는 것입니다.
어쨌든 종종 다음과 같은 결과를 얻습니다.
interface IShape
{
double intersectWith(Triangle t);
double intersectWith(Rectangle r);
double intersectWith(Circle c);
}
이것의 문제점은 "IShape"의 모든 구현을 결합했다는 것입니다. 계층 구조에 새 모양을 추가 할 때마다 다른 모든 "모양"구현도 변경해야한다는 것을 암시했습니다.
때때로 이것은 올바른 최소한의 디자인이지만 충분히 생각해보십시오. 당신의 디자인은 않습니다 정말 당신이 두 가지 유형에 파견 할 필요가 있음을 의무화? 다중 방법의 조합 폭발 각각을 작성 하시겠습니까?
종종 다른 개념을 도입하여 실제로 작성해야하는 조합의 수를 줄일 수 있습니다.
interface IShape
{
Area getArea();
}
class Area
{
public double intersectWith(Area otherArea);
...
}
물론, 상황에 따라 다릅니다. 때로는 이러한 모든 사례를 처리하기 위해 코드를 작성해야 할 때가 있습니다.하지만 잠시 멈춰서 잠시 생각하고 비지터를 사용하는 것이 좋습니다. 나중에 많은 고통을 덜어 줄 수 있습니다.
싱글 톤-싱글 톤 X를 사용하는 클래스는보기 어렵고 테스트를 위해 분리하기 어려운 종속성이 있습니다.
편리하고 이해하기 쉽기 때문에 자주 사용되지만 테스트를 정말 복잡하게 만들 수 있습니다.
Singletons are Pathological Liars를 참조하십시오 .
템플릿 메서드 패턴은 일반적으로 매우 위험한 패턴이라고 생각합니다.
DP (Design Patterns)를 피해야한다고 생각하지 않으며 아키텍처를 계획 할 때 DP를 사용하도록 강요해서는 안된다고 생각합니다. DP는 계획에서 자연스럽게 나올 때만 사용해야합니다.
처음부터 주어진 DP를 사용하기를 원한다고 정의하면, 우리가 선택한 DP가 우리의 요구에 적합하다는 보장없이 미래의 많은 디자인 결정이 그 선택의 영향을받을 것입니다.
또한 우리가해서는 안되는 한 가지는 DP를 불변의 개체로 취급하는 것입니다. 우리는 패턴을 우리의 필요에 맞게 조정해야합니다.
요약하자면, DP를 피해서는 안된다고 생각합니다. 이미 아키텍처에서 형태를 취하고있을 때이를 수용해야합니다.
Active Record는 비즈니스 로직과 지속성 코드를 혼합하도록 장려하는 남용 된 패턴이라고 생각합니다. 모델 계층에서 스토리지 구현을 숨기고 모델을 데이터베이스에 연결하는 데는 그다지 좋은 일이 아닙니다. 테이블 데이터 게이트웨이, 행 데이터 게이트웨이 및 데이터 매퍼와 같이 종종 더 나은 솔루션을 제공하고 스토리지에 더 나은 추상화를 제공하는 데 도움이되는 많은 대안 (PoEAA에 설명 됨)이 있습니다. 또한 모델을 데이터베이스에 저장할 필요 가 없습니다 . XML로 저장하거나 웹 서비스를 사용하여 액세스하는 것은 어떻습니까? 모델의 저장 메커니즘을 변경하는 것이 얼마나 쉬울까요?
즉, Active Record가 항상 나쁜 것은 아니며 다른 옵션이 과도 할 수있는 간단한 응용 프로그램에 적합합니다.
그것은 간단합니다 ... 당신에게 명확하지 않은 디자인 패턴 이나 당신이 편안하지 않은 디자인 패턴을 피하십시오 .
일부 이름을 ...
다음과 같은 비실용적 인 패턴 이 있습니다 .
Interpreter
Flyweight
다음 과 같이 이해하기 어려운 것도 있습니다 .
Abstract Factory
-생성 된 개체의 가족이있는 전체 추상적 인 공장 패턴은 보이는 것만 큼 산들 바람이 아닙니다.Bridge
-추상화와 구현이 하위 트리로 나뉘어지면 너무 추상적이 될 수 있지만 경우에 따라 매우 유용한 패턴입니다.Visitor
-더블 디스패치 메커니즘 이해는 정말 필수입니다.매우 단순 해 보이지만 원칙이나 구현과 관련된 다양한 이유로 선택이 명확하지 않은 일부 패턴이 있습니다 .
Singleton
-정말 나쁜 패턴은 아니지만 너무 많이 사용됨 (종종 거기에 적합하지 않은 경우)Observer
-훌륭한 패턴 ... 코드를 읽고 디버그하기가 훨씬 더 어려워집니다.Prototype
-컴파일러 검사에서 역 동성을 확인합니다 (좋거나 나쁠 수 있음 ...에 따라 다름).Chain of responsibility
-너무 자주 강제로 / 인위적으로 디자인에 밀어 넣음일반적으로 어딘가에 더 우아한 솔루션이 있기 때문에 이러한 "실용적이지 않은 것"의 경우 사용하기 전에 실제로 고려해야합니다.
"잡기 어려운"사람들에게는 ... 적절한 장소에서 사용하고 잘 구현 될 때 정말 큰 도움이되지만 부적절하게 사용되면 악몽입니다.
자, 다음은 ...
이것 때문에 너무 많이 맞지 않기를 바랍니다. Christer Ericsson은 실시간 충돌 감지 블로그 에서 디자인 패턴에 대한 두 개의 기사 ( 1 , 2 )를 작성했습니다 . 그의 어조는 다소 거칠고 도발적 일 수도 있지만 그 남자는 그의 물건을 알고 있기 때문에 나는 그것을 미치광이의 열광이라고 무시하지 않을 것입니다.
일부는 서비스 로케이터 가 안티 패턴 이라고 말합니다 .
관찰자 패턴에 대한 답이 많고 매우 일반적인 경우에 작동하지만 시스템이 더 복잡 해짐에 따라 OnBefore (), OnAfter () 알림이 필요하고 종종 비동기 작업을 게시하여 재개를 방지해야하는 악몽이됩니다. 초조함. 훨씬 더 나은 솔루션은 계산 중에 모든 개체 액세스 (읽기 장벽 포함)를 계측하고 종속성 그래프에서 자동으로 에지를 생성하는 자동 종속성 분석 시스템을 개발하는 것입니다.
Spoike의 게시물을 보완하는 Refactoring to Patterns 는 좋은 읽기입니다.
반복자는 피해야 할 또 하나의 GoF 패턴이거나 최소한 대안이없는 경우에만 사용합니다.
대안은 다음과 같습니다.
for-each 루프. 이 구조는 대부분의 주류 언어에 존재하며 대부분의 경우 반복자를 방지하는 데 사용할 수 있습니다.
LINQ 또는 jQuery의 선택기. 컨테이너의 모든 개체를 처리해야하는 것은 아니므로 for-each가 적절하지 않을 때 사용해야합니다. 반복기와 달리 선택기는 처리 할 종류의 개체를 한곳에서 확인할 수 있습니다.
yield
반복자를 통해 LINQ가 가능해 졌다고 생각 합니다. Eric White는 C # 3.0에서 이에 대해 몇 가지 훌륭한 토론을했습니다 : blogs.msdn.com/b/ericwhite/archive/2006/10/04/… . 또한 반복기를 사용하는 코 루틴에 대한 Jeremy Likness의 토론을 확인하세요. wintellect.com/CS/blogs/jlikness/archive/2010/03/23/… .