2016-10-14 2 views
1

외부 API 가져 오기를 사용하고 데이터를 표시하고 있습니다.추상 외부 API

유연성을 위해 API에서 코드를 완전히 분리하고 자체 정의 된 데이터 구조로 작업하려고합니다. 여기

간단한 그래픽 개요 : enter image description here

여기에 좀 더 미장 예를 들어 작업을 만들려면 :

이의 데이터를 가정 해 보자는 사람에 관한 것입니다 :

API v1.0을 {"name": "John"}을 뱉어 API v1.1은 {"pName": "John"}을 출력합니다.

interface IPersonDataStructure { 
    name : string; 
} 

interface IPersonDataParser { 
    parse(input: string) : IPersonDataStructure; 
} 
: 대한 데이터 자체에 대한 구조로 (API 응답을 구문 분석) 파서 하나 하나를이 작은 변화가 내가 내부적으로 두 개의 인터페이스를 원하는 내 코드를 깰 것을 방지하기 위해

// This class uses any parser which implements IPersonDataParser 
// And uses IPersonDataStructure 
class Person { 

} 

내가 붙어 곳이다 :

는 그럼 난 데이터 구조로 파서을 결합하는 클래스를 갖고 싶어! 나는이 둘을 어떻게 합칠 지 모른다! 파서가 (함수와 같은 예) 비 저장해야하기 때문에

let aPerson = new Person(new Parser(data)) 

:

나는 사람의 인스턴스 당 인스턴스의 아이디어를 좋아하지 않는다.

문제는 타이프 라이터 나 클래스로 그렇게하는 것을 허용하지 않았다입니다 :

class Parser implements IPersonDataParser { 
    static public function parse(data : string) : IPersonDataStructure { 
     return {...} 
    } 
} 

class Person { 
    private _data : IPersonDataStructure; 

    constructor(data : string, parser : IPersonDataParser) { 
     this._data = parser.parse(data) 
    } 
} 

콜백이 옵션 만 내가 그들의 서명을 검증 할 수있는 경우이다.

예를 들어이 제대로 확인하지 않습니다 :이 문제를 해결하는 방법에 대한

type PersonDataParser = (data : string) => IPersonDataStructure; 

// Whoops.. argument is missing! 
let aParser =() => { 
    return {...} 
} 

let aPerson = new Person('data', aParser) 

어떤 제안?

+0

여기에서 다루려고하는 문제가 정확히 무엇입니까? – toskv

+0

설명 된 기능을 깨끗한 방법으로 구현하려고합니다. – d3L

+0

이것은 실제로 stackoverflow 핸들 유형이 아닙니다. 어쩌면 코드 검토 스택 교환 웹 사이트를 사용해 보시겠습니까? 여기서는 많은 의견을 바탕으로 한 솔루션을 생성 할 것입니다. :) – toskv

답변

1

첫째, 당신은 정적 메서드를 가질 수 있으며, 인터페이스 만족 한 -이 같은 모든 사용 타입 추론 및 구조 유형 :

interface IPersonDataStructure { 
    name : string; 
} 

interface IPersonDataParser { 
    parse(input: string) : IPersonDataStructure; 
} 

class Parser { 
    public static parse(data : string) : IPersonDataStructure { 
     return { name: 'Steve' }; 
    } 
} 

class Person { 
    private _data : IPersonDataStructure; 

    constructor(data : string, parser : IPersonDataParser) { 
     this._data = parser.parse(data) 
    } 
} 

let person = new Person('', Parser); 

나는 아마 Person 그냥 사람을 나타내는 디자인을 선호하는 것을 건설 될 수 있도록 매퍼 (mapper)를 가져갈 필요가 없었습니다. 더 비슷해 ...

interface IPersonDataStructure { 
    name : string; 
} 

class Person { 
    constructor(private data : IPersonDataStructure) { 
    } 
} 

class PersonMapper { 
    public static map(data: string): Person { 
     return new Person({ 
      name: 'Steve' 
     }); 
    } 
} 

let person = PersonMapper.map('...'); 

버전 번호가 데이터의 일부인 경우 올바른 매핑을 결정하는 데 사용할 수 있습니다.

1

왜 API에서 반환 된 두 속성 중 하나를 확인하는 어댑터를 만들지 않습니까?또한

interface ApiResponse { 
    name?: string; 
    pName?: string; 
} 

class Person { 
    public name: string; 

    constructor (name: string) { 
     this.name = name; 
    } 
} 

class ApiResponseAdapter { 
    private getName(response: ApiResponse): string { 
     if (response.pName) return pName; 
     if (response.name) return name; 

     // if neither are set, return null 
     return null; 
    } 

    public adapt(response: ApiResponse): Person { 
     let name = this.getName(response); 

     if (name === null) { 
      throw new Error("Invalid name for response: " + JSON.stringify(response)); 
     } 

     return new Person(name); 
    } 
} 

당신이 행동을 처리하기 위해 구현을 갖춘베이스 ApiResponse 인터페이스 할 수 : 다른 두 개의 확장되는 추상 BaseApiResponse 클래스를

interface ApiResponse { 
    name: string; 
} 

class Api_V1_0_Response implements ApiResponse { 
    public name: string; 

    constructor (json: any) { 
     this.name = json["name"]; 
    } 
} 

class Api_V1_1_Response implements ApiResponse { 
    public name: string; 

    constructor (json: any) { 
     this.name = json["pName"]; 
    } 
} 

class Person { 
    public name: string; 

    constructor (name: string) { 
     this.name = name; 
    } 
} 

class ApiResponseAdapter { 
    public adapt(response: ApiResponse): Person { 
     return new Person(
      response.name 
     ); 
    } 
} 

을 또는 한 단계 더 가서이를 :

interface ApiResponse { 
    name: string; 
} 

abstract class BaseApiResponse implements ApiResponse { 
    public name: string; 

    constructor (nameKey: string, json: any) { 
     this.name = json[nameKey]; 
    } 
} 

class Api_V1_0_Response extends BaseApiResponse { 
    constructor (json: any) { 
     super("name", json); 
    } 
} 

class Api_V1_1_Response extends BaseApiResponse { 
    constructor (json: any) { 
     super("pName", json); 
    } 
} 

class Person { 
    public name: string; 

    constructor (name: string) { 
     this.name = name; 
    } 
} 

class ApiResponseAdapter { 
    public adapt(response: ApiResponse): Person { 
     return new Person(
      response.name 
     ); 
    } 
} 
관련 문제