코드를 디자인 할 때는 두 가지 옵션이 있습니다.
- 그냥 끝내십시오.이 경우 거의 모든 솔루션이 효과가 있습니다.
- 언어 주의적 이념을 활용하는 해결책을 설계하고 해결책을 설계하십시오 (이 경우 OO 언어-다형성을 결정 수단으로 사용)
말할 것도 없기 때문에 나는 두 가지 중 첫 번째에 집중하지 않을 것입니다. 방금 작동 시키려면 코드를 그대로 두십시오.
그러나 만약 당신이 그것을 pedantic 한 방법으로하고 실제로 원하는 방식으로 디자인 패턴의 문제를 해결한다면 어떻게 될까요?
다음 프로세스를 볼 수 있습니다.
OO 코드를 디자인 할 때 코드에있는 대부분의 if
코드가있을 필요는 없습니다. 당연히 int
s 또는 float
s 와 같은 두 스칼라 유형을 비교하려는 경우을 가질 가능성이 if
있지만 구성에 따라 프로 시저를 변경하려면 다형성 을 사용 하여 원하는 것을 달성 할 수 있습니다 . if
의) 객체가 인스턴스화 장소, 귀하의 비즈니스 로직에서 -에 공장 .
현재 귀하의 프로세스는 4 가지 경로를 거칠 수 있습니다.
data
암호화되거나 압축되지 않습니다 (아무것도 호출하지 않음, return data
)
data
압축 compress(data)
되어있다
data
암호화되어 있습니다 (전화 encrypt(data)
를 거십시오)
data
압축 및 암호화 (호출 encrypt(compress(data))
및 반환)
4 가지 경로를 보면 문제가 있습니다.
데이터를 조작 한 다음 반환하는 다른 메소드를 3 (이것은 아무것도 호출하지 않는 경우 4) 프로세스를 호출하는 하나의 프로세스가 있습니다. 메소드는 이름이 다르고 , 공개 API (메소드가 동작을 전달하는 방법)가 다릅니다 .
어댑터 패턴을 사용하여 발생한 이름 colision (공용 API를 통합 할 수 있음)을 해결할 수 있습니다. 간단히 말해서, 어댑터는 호환되지 않는 두 개의 인터페이스가 함께 작동하도록 도와줍니다. 또한 어댑터는 API 구현을 통합하려는 클래스의 새 어댑터 인터페이스를 정의하여 작동합니다.
이것은 구체적인 언어가 아닙니다. 그것은 일반적인 접근 방식이며, 모든 키워드는 C #과 같은 언어에서 제네릭 ( <T>
)으로 바꿀 수 있습니다 .
지금 당장 압축과 암호화를 담당하는 두 개의 클래스를 가질 수 있다고 가정하겠습니다.
class Compression
{
Compress(data : any) : any { ... }
}
class Encryption
{
Encrypt(data : any) : any { ... }
}
엔터프라이즈 세계에서는 이러한 특정 클래스조차도 class
키워드로 대체 interface
되거나 (C #, Java 및 / 또는 PHP와 같은 언어를 처리해야하는 경우) 키워드 와 같은 인터페이스로 대체 될 가능성이 있지만 class
키워드는 그대로 있습니다. Compress
및 Encrypt
방법은로 정의 될 수 순수 가상 ++ 당신에게, C 코드를해야한다.
어댑터를 만들기 위해 공통 인터페이스를 정의합니다.
interface DataProcessing
{
Process(data : any) : any;
}
그런 다음 인터페이스를 유용하게 사용하려면 구현을 제공해야합니다.
// when neither encryption nor compression is enabled
class DoNothingAdapter : DataProcessing
{
public Process(data : any) : any
{
return data;
}
}
// when only compression is enabled
class CompressionAdapter : DataProcessing
{
private compression : Compression;
public Process(data : any) : any
{
return this.compression.Compress(data);
}
}
// when only encryption is enabled
class EncryptionAdapter : DataProcessing
{
private encryption : Encryption;
public Process(data : any) : any
{
return this.encryption.Encrypt(data);
}
}
// when both, compression and encryption are enabled
class CompressionEncryptionAdapter : DataProcessing
{
private compression : Compression;
private encryption : Encryption;
public Process(data : any) : any
{
return this.encryption.Encrypt(
this.compression.Compress(data)
);
}
}
이렇게하면 4 개의 클래스로 끝나게되는데, 각 클래스는 완전히 다른 것을 수행하지만 각 클래스는 동일한 공용 API를 제공합니다. Process
방법.
none / encryption / compression / both 결정을 처리하는 비즈니스 로직에서 DataProcessing
이전에 디자인 한 인터페이스에 따라 개체를 디자인합니다 .
class DataService
{
private dataProcessing : DataProcessing;
public DataService(dataProcessing : DataProcessing)
{
this.dataProcessing = dataProcessing;
}
}
프로세스 자체는 다음과 같이 간단 할 수 있습니다.
public ComplicatedProcess(data : any) : any
{
data = this.dataProcessing.Process(data);
// ... perhaps work with the data
return data;
}
더 이상 조건이 없습니다. 클래스 DataService
는 데이터가 dataProcessing
멤버 에게 전달 될 때 실제로 어떤 작업을 수행할지 모릅니다. 실제로 데이터에 신경 쓰지 않으며 책임이 없습니다.
이상적으로, 작성한 4 개의 어댑터 클래스를 테스트하여 단위 테스트를 수행하여 작동하는지 테스트하고 테스트에 통과시키는 것이 이상적입니다. 그리고 그들이 통과하면 코드에서 호출하는 위치에 관계없이 작동 할 것입니다.
그래서이 방법으로 if
더 이상 내 코드에 s 가 없을 것입니까?
아니요. 비즈니스 로직에 조건이있을 가능성은 적지 만 여전히 어딘가에 있어야합니다. 장소는 당신 공장입니다.
그리고 이것은 좋습니다. 생성과 실제로 코드 사용에 대한 우려를 분리합니다. 팩토리를 안정적으로 만들면 (Java에서 Google 의 Guice 프레임 워크 와 같은 기능을 사용할 수있는 경우도 있음 ) 비즈니스 로직에서 올바른 클래스를 선택하는 것에 대해 걱정하지 않아도됩니다. 당신은 당신 공장이 일하고 알고있는 것을 배달 할 것이라는 것을 알고 있기 때문에.
이러한 모든 클래스, 인터페이스 등이 필요합니까?
이것은 우리를 처음으로 돌아옵니다.
OOP에서 다형성을 사용할 경로를 선택하고 실제로 디자인 패턴을 사용하고 싶거나 언어의 기능을 이용하고 싶거나 모든 것을 따르고 싶다면 모든 것이 객체 이데올로기입니다. 그럼에도 불구하고이 예제는 필요한 모든 팩토리를 보여 주지도 Compression
않으며, Encryption
클래스 를 리팩토링하고 대신 인터페이스로 만들려면 구현도 포함해야합니다.
결국 당신은 매우 특정한 것들에 초점을 맞춘 수백 개의 작은 클래스와 인터페이스로 끝납니다. 반드시 나쁘지는 않지만 원하는 두 숫자를 추가하는 것만 큼 간단하게 수행하는 것이 가장 좋은 해결책은 아닙니다.
당신이 그것을 완료하고 신속하게 얻을하려는 경우, 당신은 잡을 수 Ixrec의 솔루션 적어도 제거 관리, else if
그리고 else
내 생각에, 더 일반보다 조금있다, 블록, if
.
이것이 좋은 OO 디자인을 만드는 나의 방법임을 고려하십시오 . 구현이 아닌 인터페이스에 코딩하는 것은 지난 몇 년 동안 내가해온 방법이며 가장 편한 방법입니다.
나는 개인적으로 if-less 프로그래밍을 더 좋아하고 5 줄의 코드에 대한 더 긴 솔루션을 훨씬 더 높이 평가할 것입니다. 코드를 디자인하는 데 익숙하고 읽는 것이 매우 편안합니다.
업데이트 2 : 내 솔루션의 첫 번째 버전에 대한 토론이 활발했습니다. 토론은 주로 저에 의한 것이며, 사과드립니다.
나는 해결책을 보는 방법 중 하나이지만 유일한 해결책은 아닌 방식으로 답변을 편집하기로 결정했습니다. 또한 데코레이터 부분을 제거했는데 대신 외관을 의미했습니다. 어댑터는 외관 변형이기 때문에 결국 완전히 빠져 나가기로 결정했습니다.
if
진술 이있을 가능성이 있습니까?