[5 분] 초보 수련 의 디자인 모델: 6 대 디자인 원칙
목차
필 자 는 풋내기 로 서 간단 한 코드 와 이해 하기 쉬 운 문구 로 이 몇 가지 원칙 의 특성 과 응용 장면 을 설명 하려 고 한다.
이 여섯 가지 원칙 은 단일 직책 원칙, 인터페이스 격 리 원칙, 리 씨 교체 원칙, 디 미트 법칙, 후진 원칙, 개폐 원칙 에 의존 하 는 것 이다.
단일 직책 원칙
단일 직책 원칙 (SRP: Single responsibility principle) 은 한 가지 유형 중 한 가지 원인 만 이 유형의 변 화 를 일 으 켜 야 한다 고 규정 한다.
단일 직책 원칙 의 핵심 은 결합 을 해제 하고 내부 집적 성 을 강화 하 는 것 이다.
질문:
//
public class DatabaseContext { }
public class Test
{
private readonly DatabaseContext _context;
public Test(DatabaseContext context)
{
_context = context;
}
//
public void UserLogin() { }
//
public void UserLogout() { }
//
public void AddUser() { }
//
public void UpdateUser() { }
//
public void DeleteUser() { }
}
Test 는 직책 P1 (사용자 로그 인 및 탈퇴) 과 P2 (사용자 계 정 관리) 두 가지 직책 을 담당 하 며, 직책 P1 의 수요 변화 로 유형 을 수정 해 야 할 경우 정상 적 인 직책 P2 의 기능 이 고장 날 수 있 습 니 다.
위의 코드 에서 두 직책 이 결합 되 어 여러 가지 기능 을 맡 았 다.
한 가지 유형 중 한 가지 원인 만 이 유형의 변 화 를 일 으 켜 야 한다. 또한 한 가지 유형 은 하나의 기능 만 책임 지고 유형 중의 코드 는 밀접 한 관 계 를 가 져 야 한다.
위의 예제 코드 는 매우 간단 해서 우 리 는 자 연 스 럽 게 하나의 종 류 를 두 부분 으로 나 눌 수 있다.
//
public class DatabaseContext { }
public class Test1
{
private readonly DatabaseContext _context;
public Test1(DatabaseContext context)
{
_context = context;
}
//
public void UserLogin() { }
//
public void UserLogout() { }
}
public class Test2
{
private readonly DatabaseContext _context;
public Test2(DatabaseContext context)
{
_context = context;
}
//
public void AddUser() { }
//
public void UpdateUser() { }
//
public void DeleteUser() { }
}
따라서 단일 직책 원칙 의 해결 방법 은 서로 다른 직책 을 서로 다른 유형 이나 모듈 에 밀봉 하 는 것 이다.
인터페이스 격 리 원칙
인터페이스 격 리 원칙 (ISP: Interface Segregation Principle) 은 인 터 페 이 스 를 세분 화해 야 한다. 클래스 의 계승 은 최소 입도 에 세 워 지고 클 라 이언 트 가 계승 하 는 인 터 페 이 스 를 확보 하 는 데 모든 방법 이 필요 하 다.
필 자 는 외국 의 일부 자 료 를 찾 아 보 았 는데 대부분 인터페이스 격 리 원칙 을 다음 과 같이 정의 했다.
“Clients should not be forced to depend upon interfaces that they do not use.”
고객 에 게 사용 하지 않 는 방법 에 의존 하도록 강요 해 서 는 안 된다 는 뜻 이다.
이 원칙 에 대한 해석 에 있어 서 이 글 은 매우 투철 하 다.
https://stackify.com/interface-segregation-principle/
비대 한 인 터 페 이 스 를 더 작고 구체 적 인 인터페이스 로 나 누 어 인터페이스 가 담당 하 는 기능 을 더욱 단일 하 게 해 야 한다.
목적: 소프트웨어 를 여러 개의 독립 된 부분 으로 나 누 어 변경 해 야 할 부작용 과 빈 도 를 줄인다.
필 자 는 두 가지 측면 에서 논술 하고 싶다.
첫째, 여러 종류의 동물 을 묘사 할 때 우 리 는 서로 다른 종류의 동물 을 분류 할 수 있다.하지만 아직 부족 합 니 다. 예 를 들 어 조류 에서 우리 가 기억 하 는 새 의 특징 은 새 가 날 수 있 지만 펭귄 은 날 지 못 합 니 다 ~
그러면 혈액의 색깔, 척추 유 무 등 종의 특징 을 세분 화해 야 한다.
둘째, 우 리 는 아래 코드 를 통 해 표현 할 수 있다.
//
public interface IUserLogin
{
//
void Login();
//
void Logout();
}
//
public interface IUserInfo
{
//
void AddUser();
//
void UpdateUser();
//
void DeleteUser();
}
위의 두 개의 인 터 페 이 스 는 서로 다른 기능 을 실현 하고 서로 교차 되 지 않 으 며 완벽 하 다.
다음은 IUserLogin 인 터 페 이 스 를 계승 한 두 개의 코드 를 살 펴 보 겠 습 니 다.
// ,
public class Test1 : IUserLogin
{
public void Login(){}
public void Logout(){}
}
public class Test2 : IUserLogin
{
public void Login()
{
//
}
public void Logout()
{
}
}
Test 1 에 대해 서 는 로그 인 과 로그아웃 두 상태 에 따라 서로 다른 조작 을 합 니 다.
그러나 Test 2 에 대해 서 는 이 상태 에 로그 인하 기만 하면 됩 니 다. 다른 상황 은 상관 없습니다.그렇다면
Logout()
그 에 게 는 전혀 소 용이 없다. 이것 이 바로 인터페이스 오염 이다.위의 코드 는 인터페이스 격 리 원칙 을 위반 했다.
그러나 인터페이스 격 리 원칙 은 인 터 페 이 스 를 너무 많이 세분 화하 기 쉽다 는 단점 이 있다.한 항목 에 수천 개의 인터페이스 가 나타 나 면 유지 보수 의 재난 이 될 것 이다.
따라서 인터페이스 격 리 원칙 은 유연 하 게 사용 해 야 한다. Test 2 에 있어 서 한 가지 방법 을 더 계승 하 는 것 은 큰 문제 가 없 으 며 사용 하지 않 으 면 된다.ASP. NET Core 에는 이런 실현 이 많다.
public void Function()
{
throw new NotImplementedException();
}
예제 주소:https://github.com/dotnet/aspnetcore/search?q=throw+new+NotImplementedException()%3B&unscoped_q=throw+new+NotImplementedException()%3B
제4 장 에서 작 가 는 인터페이스 격 리 원칙 에 대해 네 가지 요 구 를 정리 했다.
인 터 페 이 스 는 되도록 작 게: 비대 한 (Fat) 인터페이스 가 나타 나 지 않 습 니 다.
인 터 페 이 스 는 높 은 내부 집적: 인터페이스, 클래스, 모듈 의 처리 능력 을 향상 시 켜 야 한다.
맞 춤 형 서비스: 작은 입자 의 인 터 페 이 스 는 큰 인 터 페 이 스 를 구성 하고 새로운 기능 을 유연 하 게 맞 출 수 있다.
인터페이스의 디자인 에 한계 가 있다. 인터페이스의 입도 가 합 리 적 인지 아 닌 지 를 평가 하 는 고정 적 인 기준 이 있 기 어렵다.
단일 직책 원칙 과 인터페이스 격 리 원칙 에 대한 관계 와 대비 도 있다.
단일 직책 원칙 은 서비스 제공 자의 측면 에서 볼 때 내부 적 이 고 단일 한 직책 의 기능 을 제공 하 는 것 이다.
인터페이스 격 리 원칙 은 사용자 의 측면 에서 볼 때 높 은 내부 집적 과 낮은 결합 을 실현 하 는 것 이다.
인터페이스 격 리 원칙 의 입 도 는 더욱 작 을 수 있 고 여러 인 터 페 이 스 를 통 해 단일 직책 원칙 에 부합 되 는 유형 을 유연 하 게 구성 할 수 있다.
우 리 는 단일 직책 원칙 은 유형 을 중심 으로 토론 하 는 것 을 보 았 다.인터페이스 격 리 원칙 은 인터페이스 에 대해 토론 하 는 것, 즉 추상 에 대해 토론 하 는 것 이다.
개폐 원칙
개폐 원칙 (Open / Closed Principle) 규정:
"소프트웨어 의 대상 (클래스, 모듈, 함수 등) 은 확장 에 대해 개방 적 이 어야 하지만 수정 에 대해 서 는 폐쇄 적 입 니 다."
-- '오 브 젝 트 지향 소프트웨어 건설' 저자 버 트 랜 드 마 이 어
개폐 원칙 은 하나의 실체 가 소스 코드 를 바 꾸 지 않 는 전제 에서 행 위 를 변경 할 수 있 도록 하 는 것 을 의미한다.클래스 의 변경 은 원본 코드 를 수정 하 는 것 이 아니 라 코드 를 추가 하여 이 루어 집 니 다.
개폐 원칙 에는 메 야 개폐 원칙, 다 태 개폐 원칙 이 있다.
현재 대부분의 경우 개폐 원칙 은 다 중 개폐 원칙 을 말한다.
다 중 개폐 원칙 에 대해 필 자 는 자 료 를 조회 한 결과 이 인 터 페 이 스 는
Interface
가 아니 라 추상 적 인 방법, 가상 방법 을 말 하 는 것 을 발견 했다.물음: 대상 을 향 한 3 대 특성 은 무엇 입 니까?답: 봉인, 계승, 다 태.
그래, 다 중 개폐 원칙 은 바로 이 다 태 를 가리킨다.그러나 재 업로드 (재 작성), 숨 기기 에는 대응 하지 않 는 것 이 원칙 이다.
이것 은 예시 이다.
//
public class UserLogin
{
public void Login() { }
public void Logout() { }
public virtual void A() {/* */}
public virtual void B() {/* */ }
}
public class UserLogin1 : UserLogin
{
public void Login(string userName) { } // ?
public override void A() { } // √
public override void B() { } // √
public new void Logout() { } // ?
}
다 중 개폐 원칙 의 장점 은 추상 을 도입 하여 두 가지 소나무 결합 을 하 게 하고 코드 를 수정 하지 않 는 전제 에서 하위 클래스 로 부모 클래스 (리 씨 교체 원칙) 를 교체 할 수 있다 는 것 이다.
인터페이스 와 추상 류 의 차이?
필 자 는 인 터 페 이 스 는 공 통 된 기준 을 실현 하기 위 한 것 이 라 고 어렴풋이 기억 했다.추상 은 코드 의 재 활용 을 위 한 것 이다.
물론 인터페이스 와 추상 은 리 씨 교 체 를 실현 할 수 있다.
개폐 원칙 을 통 해 우 리 는 다 형 을 알 수 있 고 인터페이스 와 추상 적 인 응용 장면 도 알 수 있다.
또 하나의 문 제 는 개폐 원칙 이 기능 을 수정 하거나 추가 할 때 기 존 코드 를 수정 하 는 것 이 아니 라 하위 클래스 를 통 해 이 루어 져 야 한 다 는 것 이다.부모 클래스 의 코드 를 다시 불 러 오고 숨 길 수 있 습 니까?
한편, 개폐 원칙 의 핵심 은 구조 가 추상 적 이어서 자 류 파생 을 통 해 확 대 를 실현 하 는 것 이다.그런 얘 기 는 안 한 것 같은 데.
필 자 는 옳지 않다 고 생각한다...
먼저 아래 의 리 씨 교체 원칙 과 결합 하여 우 리 는 이 문 제 를 다시 토론 합 니까?
리 씨 교체 원칙
리 씨 교체 원칙 (LSP: Liskov Substitution Principle) 은 부 류 가 나타 나 는 곳 은 자 류 가 모두 나타 날 수 있다 고 요구 했다.
이것 은 자 류 가 반드시 부계 와 같은 행 위 를 해 야 한 다 는 것 을 요구한다.하위 클래스 가 모든 부모 클래스 의 인 스 턴 스 를 교체 할 수 있 을 때 만 리 씨 교체 원칙 에 부합 한다.
리 씨 교체 원칙 의 제약:
그래서 우 리 는 개폐 원칙 중의 예 를 보 았 다. 자 류 는 부 류 를 다시 태 워 야 하 는 방법 이 아 닐 까?new 키 워드 를 사용 하여 부모 클래스 를 숨 기 는 방법 을 사용 해 야 합 니까?자 류 의 계승 을 확보 하기 위해 서 는 부 류 와 일치 하 는 특성 을 가지 고 있 으 므 로 이렇게 하 는 것 을 권장 하지 않 습 니 다. 친.
개폐 원칙 을 실현 하 였 으 니 당연히 리 씨 교체 원칙 을 사용 할 수 있다.
후진 원칙 에 의존 하 다.
후진 원칙 (Dependence Inversion Principle) 에 의존 하려 면 프로그램 이 추상 적 인 인터페이스 에 의존 하고 구체 적 인 실현 에 의존 하지 말 아야 한다.
우 리 는 코드 에서 천천히 이론 을 발전 시 키 고 유도 할 수 있다.
//
public class UserLogin
{
public void Login(){}
public void Logout(){}
}
public class Test1 : UserLogin { }
public class Test2
{
private readonly UserLogin userLogin = new UserLogin();
}
public class Test3
{
private readonly UserLogin _userLogin;
public Test3(UserLogin userLogin)
{
_userLogin = userLogin;
}
}
위의 코드 에서 Test 1, Test 2, Test 3 는 모두 UserLogin 에 의존 합 니 다.위의 코드 에 무슨 문제 가 있 는 지 는 말 하지 않 고 거꾸로 하 는 원칙 에 따라 코드 를 이렇게 작성 해 야 합 니 다.
//
public interface IUserLogin
{
void Login(); //
void Logout(); //
}
//
public class UserLogin1 : IUserLogin
{
public void Login(){}
public void Logout(){}
}
//
public class UserLogin2 : IUserLogin
{
public void Login(){}
public void Logout(){}
}
public class Test4
{
private readonly IUserLogin _userLogin;
public Test4(IUserLogin userLogin)
{
_userLogin = userLogin;
}
}
후진 원칙 에 의존 하 는 것 은 추상 을 도입 하 는 데 있다. 이런 추상 은 고급 모듈 과 바 텀 모듈 을 서로 분리 하 는 것 이다.고 층 모듈 과 바 텀 모듈 의 소나무 결합, 바 텀 모듈 의 변동 은 고 층 모듈 이 필요 없 이도 변동 해 야 한다.
의존 은 원칙 에 두 가지 사상 을 초래한다.
추상 에 의존 하기 때문에 바 텀 모듈 은 추상 을 실현 하 는 모듈 을 임의로 교체 할 수 있다.
리 씨 교체 원칙 은 자 류 의 부 류 를 구 하 는 행위 가 일치 하고 자 류 는 부 류 를 교체 할 수 있다 는 것 이다.
후진 원칙 에 의존 하면 모든 방법의 행 위 는 완전히 다 를 수 있다.
디 미트 의 법칙
디 미트 법칙 (Law of Demeter) 은 두 가지 유형 간 에 가능 한 한 최소한 의 관 계 를 유지 하도록 요구한다.
예 를 들 어 대상 A 는 대상 B 를 직접 호출 하지 말고 중간 대상 C 를 통 해 통신 을 유지 해 야 한다.
참고 하 다https://en.wikipedia.org/wiki/Law_of_Demeter
장점: 느슨 한 결합 으로 의존 도가 적 습 니 다.
단점: 많은 포장 코드 를 작성 하여 복잡 한 읽 기 를 늘 리 고 모듈 간 의 통신 효율 이 낮 아 집 니 다.
필 자 는 많은 자 료 를 찾 았 는데 모두 자바 의...
결국 C \ # 로 된 글 이 있 더 라 고요.https://www.cnblogs.com/zh7791/p/7922960.html
일반적으로 디 미트 원칙, 코드 의존 도치 원칙 과 리 씨 교체 원칙 등 은 디 미트 법칙 에 부합 한다 고 언급 하지 않 는 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.