[5 분] 초보 수련 의 디자인 모델: 6 대 디자인 원칙

10680 단어
[5 분] 초보 수련 의 디자인 모델: 6 대 디자인 원칙
목차
  • [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
    일반적으로 디 미트 원칙, 코드 의존 도치 원칙 과 리 씨 교체 원칙 등 은 디 미트 법칙 에 부합 한다 고 언급 하지 않 는 다.

    좋은 웹페이지 즐겨찾기