문제
파일 에서 데이터를 읽는 방법 DataSource
을 제공 하는 클래스를 가지고 있다고 가정 해 봅시다 .ReadData
.mdb
var source = new DataSource("myFile.mdb");
var data = source.ReadData();
몇 년 후, 나는 .xml
파일 외에도 .mdb
데이터 소스 로 파일 을 지원할 수 있기를 원합니다 . "데이터 읽기"구현은 파일 .xml
과 .mdb
파일 마다 상당히 다릅니다 . 따라서 처음부터 시스템을 설계하려면 다음과 같이 정의하십시오.
abstract class DataSource {
abstract Data ReadData();
static DataSource OpenDataSource(string fileName) {
// return MdbDataSource or XmlDataSource, as appropriate
}
}
class MdbDataSource : DataSource {
override Data ReadData() { /* implementation 1 */ }
}
class XmlDataSource : DataSource {
override Data ReadData() { /* implementation 2 */ }
}
Factory 메소드 패턴을 완벽하게 구현했습니다. 불행히도 DataSource
라이브러리에 있으며 코드를 리팩터링하면 기존의 모든 호출이 중단됩니다.
var source = new DataSource("myFile.mdb");
라이브러리를 사용하는 다양한 클라이언트에서. 내가 왜 공장 식 방법을 사용하지 않았습니까?
솔루션
이것들은 내가 생각해 낼 수있는 해결책입니다.
DataSource 생성자가 하위 유형 (
MdbDataSource
또는XmlDataSource
)을 반환하도록 합니다. 그것은 내 모든 문제를 해결할 것입니다. 불행히도 C #은이를 지원하지 않습니다.다른 이름을 사용하십시오.
abstract class DataSourceBase { ... } // corresponds to DataSource in the example above class DataSource : DataSourceBase { // corresponds to MdbDataSource in the example above [Obsolete("New code should use DataSourceBase.OpenDataSource instead")] DataSource(string fileName) { ... } ... } class XmlDataSource : DataSourceBase { ... }
그것이 코드를 이전 버전과 호환 가능하게 유지하기 때문에 결국 사용했습니다 (즉,
new DataSource("myFile.mdb")
여전히 작동하도록 호출 ). 결점 : 이름은 설명 그대로가 아닙니다.DataSource
실제 구현을위한 "래퍼"를 만듭니다 .class DataSource { private DataSourceImpl impl; DataSource(string fileName) { impl = ... ? new MdbDataSourceImpl(fileName) : new XmlDataSourceImpl(fileName); } Data ReadData() { return impl.ReadData(); } abstract private class DataSourceImpl { ... } private class MdbDataSourceImpl : DataSourceImpl { ... } private class XmlDataSourceImpl : DataSourceImpl { ... } }
단점 : 모든 데이터 소스 방법 (예
ReadData
:)은 상용구 코드로 라우팅해야합니다. 상용구 코드가 마음에 들지 않습니다. 중복되고 코드가 복잡합니다.
어떤 거기에 우아한 내가 놓친 것을 해결책은?
new
클래스 객체의 메소드가 아니기 때문에 부끄러운 일입니다 (따라서 클래스 자체를 메타 클래스라고하는 기술을 서브 클래스 화하고 new
실제로 수행 하는 것을 제어 할 수 는 있지만) C # (또는 Java 또는 C ++)의 작동 방식은 아닙니다.