>  기사  >  Java  >  Java 디자인 패턴에 따른 7가지 원칙

Java 디자인 패턴에 따른 7가지 원칙

高洛峰
高洛峰원래의
2016-12-12 13:50:051517검색

최근 몇 년 동안 사람들은 코드 재사용성을 확보하고 코드 유지 관리성을 높이기 위해 디자인 패턴을 적극적으로 옹호하고 사용하고 있습니다. 디자인 패턴의 구현은 코드 재사용성과 유지 관리성을 높이기 위한 몇 가지 원칙을 따릅니다. 디자인 패턴은 객체 지향의 세 가지 주요 특성을 이해하는 데 매우 영감을 줍니다. 디자인 패턴을 보지 않고는 깊이 이해하기 어렵습니다. 객체지향 개발의 이점에 대해 알아봅니다. 학습 초기에는 이러한 모드를 통합하는 것이 어렵기 때문에 코딩하기 전에 더 많이 생각하고, 충분히 생각한 후에 코딩 연습을 시작해야 합니다. 디자인 패턴이 따라야 할 7가지 원칙은 다음과 같습니다

1. Open Close 원칙

정의: 클래스, 모듈, 기능과 같은 소프트웨어 엔터티는 확장이 가능하고 수정이 가능해야 합니다. 폐쇄.

개방형 원칙은 디자인할 때 항상 이 클래스를 충분히 고려하고 작성해야 한다는 것을 의미합니다. 새로운 요구 사항이 생기면 일부 클래스를 추가할 것입니다. . 가능하다면 원본 코드는 변경되지 않습니다. 이 원칙에는 두 가지 특성이 있습니다. 하나는 "확장에 개방적"이고 다른 하나는 "변화에 폐쇄적"입니다. 수요가 있을 경우 기존 코드를 변경하는 대신 새로운 코드를 추가하여 프로그램을 변경합니다. 이것이 "개방-폐쇄 원칙"의 정신입니다

예를 들어 처음에는 추가 프로그램만 작성하면 된다는 요구 사항이 클라이언트 클래스에서 완료되고 얼마 지나지 않아 변경이 발생하지 않았습니다. 이때 요구 사항은 뺄셈 함수를 추가하는 것이었습니다. 이때 함수를 추가하려면 원래 클래스를 수정해야 하며 이는 개방형 폐쇄 원칙을 위반하므로 프로그램을 재구성하고 추상 컴퓨팅을 추가하는 것을 고려해야 합니다. 클래스, 상속, 동적 등과 같은 일부 객체 지향 수단을 사용합니다. 클라이언트 결합에서 특정 추가 및 뺄셈을 격리함으로써 요구 사항을 계속 충족하고 변경 사항을 처리할 수 있습니다. 이때 곱셈, 나눗셈 기능을 추가해야 하는 경우 클라이언트와 덧셈, 뺄셈 클래스를 변경할 필요 없이 대신 곱셈, 나눗셈 하위 클래스만 추가하면 됩니다.
수정 사항의 절대 폐쇄는 불가능합니다. 모듈이 아무리 '폐쇄'되어도 폐쇄할 수 없는 변경 사항이 있기 때문에 설계자는 자신이 설계한 모듈을 어떤 변경으로 변경해야 할지 결정해야 합니다. 선택을 닫습니다. 그는 먼저 발생할 가능성이 가장 높은 변화의 종류를 추측한 다음 그러한 변화를 격리하기 위한 추상화를 구성해야 합니다. 처음에 코드를 작성할 때 변경 사항이 발생하지 않을 것이라고 가정하고, 발생하면 향후 동일한 종류의 변경 사항을 격리하기 위해 추상화를 만듭니다.

우리가 원하는 것은 개발이 시작된 후 가능한 변경 사항에 대해 알아보는 것입니다. 어떤 변경 사항이 발생했는지 확인하는 데 시간이 오래 걸릴수록 올바른 추상화를 만드는 것이 더 어려워집니다. 개방형-폐쇄형 원칙은 객체지향 설계의 핵심입니다. 이 원칙을 따르면 객체지향 기술이 주장하는 유지 관리성, 확장성, 재사용성 및 유연성이라는 큰 이점을 얻을 수 있습니다. 개발자는 프로그램에서 자주 변경되는 부분만 추상화해야 합니다. 그러나 미성숙한 추상화를 거부하는 것도 추상화 자체만큼 중요합니다. 개방-폐쇄 원칙은 이전 코드의 정확성을 보장할 수 있습니다. 이전 코드가 수정되지 않았기 때문에 개발자는 새로 확장된 코드에 디자인을 배치하는 데 집중할 수 있습니다.

간단히 말하면 과거는 역사가 되어서 바꿀 수 없습니다. 시간은 되돌릴 수 없기 때문입니다. 하지만 지금이나 내일 할 계획은 스스로 결정할 수 있습니다(즉, 확장).

2. Liskov 대체 원리

정의 1: T1 유형의 모든 객체 o1에 대해 T2 유형의 객체 o2가 있는 경우 T1이 정의된 모든 프로그램 P의 동작은 그렇지 않습니다. 모든 객체 o1이 o2로 대체될 때 변경되면 T2 유형은 T1 유형의 하위 유형입니다.

정의 2: 하위 유형은 상위 유형을 대체할 수 있어야 합니다.
설명: 소프트웨어 엔터티가 상위 클래스를 사용하는 경우 하위 클래스에 적용 가능해야 하며 상위 클래스 개체와 하위 클래스 개체 간의 차이를 감지할 수 없습니다. 즉, 소프트웨어에서는 상위 클래스 클래스가 대체됩니다. 하위 클래스를 사용하면 프로그램의 동작이 변경되지 않습니다.
예: 생물학적 분류에서 펭귄은 일종의 새이지만 프로그래밍 세계에서는 펭귄이 새로부터 상속받을 수 없습니다. 객체 지향 디자인에서 하위 클래스는 상위 클래스의 모든 비공개 동작과 속성을 갖습니다. 새는 날 수 있지만 펭귄은 날 수 없으므로 펭귄은 새를 상속받을 수 없습니다.

서브클래스가 부모 클래스를 대체할 수 있고 소프트웨어 유닛의 기능이 영향을 받지 않는 경우에만 부모 클래스를 재사용할 수 있고 서브클래스도 부모 클래스를 기반으로 새로운 동작을 추가할 수 있습니다. 대체 원칙은 상속과 재사용을 가능하게 합니다. 상위 클래스 유형을 사용하는 모듈을 수정 없이 확장할 수 있는 것은 바로 하위 유형의 대체 가능성 때문입니다. 그렇지 않으면 확장을 위해 열고 수정을 위해 닫는 것에 대해 어떻게 말할 수 있습니까?

리스코프 대체 원칙이 인기가 있습니다. 간단히 말하면, 하위 클래스는 상위 클래스의 기능을 확장할 수 있지만 상위 클래스의 원래 기능을 변경할 수는 없습니다. 여기에는 다음과 같은 4가지 의미 수준이 포함됩니다.

1. 하위 클래스는 상위 클래스의 추상 메서드를 구현할 수 있지만 상위 클래스의 비추상 메서드를 재정의할 수는 없습니다.

2. 서브클래스는 고유한 메서드를 추가할 수 있습니다.

3. 하위 클래스의 메서드가 상위 클래스의 메서드를 재정의하는 경우 메서드의 전제 조건(즉, 메서드의 형식 매개변수)은 상위 클래스 메서드의 입력 매개변수보다 느슨합니다.

4. 하위 클래스의 메서드가 상위 클래스의 추상 메서드를 구현할 때 메서드의 사후 조건(즉, 메서드의 반환 값)은 상위 클래스의 사후 조건보다 더 엄격합니다.

우리 자신의 프로그래밍에서 종종 Liskov 대체 원칙을 위반하는 것을 발견하게 되지만 프로그램은 여전히 ​​잘 실행되기 때문에 믿을 수 없을 것 같습니다. 그래서 모든 사람은 이 질문을 할 것입니다. 내가 Liskov 대체 원칙을 따르지 않는다고 주장하면 결과는 어떻게 될까요?

결과적으로, 작성한 코드에 문제가 발생할 가능성이 크게 높아집니다.

3. 종속성 역전 원칙

정의: 상위 수준 모듈은 하위 수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 하며 세부 사항에 의존해서는 안 됩니다. 추상화. 즉, 구현을 위한 프로그램이 아닌 인터페이스를 위한 프로그램

실제로 종속성 역전은 합의된 인터페이스를 제외하면 누구도 다른 사람에게 의존해서는 안 된다는 의미입니다. 종속성 역전은 객체 지향 설계의 징후라고 할 수 있습니다. 프로그램을 작성하는 데 어떤 언어를 사용하는지는 중요하지 않습니다. 작성 시 세부 사항, 즉 모든 종속성을 프로그래밍하는 대신 추상화를 위해 프로그래밍하는 방법을 고려하면 됩니다. 프로그램에서는 추상화로 끝납니다. 클래스나 인터페이스는 객체 지향 설계이고, 그렇지 않으면 절차적 설계입니다. 디자인의 다양한 구성 요소나 클래스가 서로 의존하면 결합도가 높아지고 유지 및 확장이 어려워지며 이는 객체 지향의 이점을 반영하지 못하게 됩니다.

의존성 역전 원칙은 수요 그룹, 개발 그룹, 테스트 그룹이 모두 동일한 요구 사항에 직면하고 해당 작업을 수행하는 팀과 같습니다. 테스트 그룹 개발팀이 이해한 요구 사항에 따라 테스트 사례를 만듭니다. 즉, 개발팀과 테스트팀이 수요 그룹을 향해 직접 작업하여 제품이 제 시간에 온라인에 출시되도록 하는 것입니다. 수요는 개발 및 테스트에 의존하지 않습니다.

종속성 역전의 원리는 추상적인 것이 세부적인 것의 가변성보다 훨씬 더 안정적이라는 사실에 기초합니다. 추상화를 기반으로 구축된 아키텍처는 세부 사항을 기반으로 구축된 아키텍처보다 훨씬 안정적입니다. Java에서 추상화는 인터페이스 또는 추상 클래스를 나타내며 세부 사항은 특정 구현 클래스를 의미합니다. 인터페이스 또는 추상 클래스를 사용하는 목적은 특정 작업을 포함하지 않고 사양 및 계약을 공식화하고 세부 사항을 구현 클래스에 표시하는 작업을 맡기는 것입니다. 완벽한.

종속성 반전 원칙의 핵심 아이디어는 인터페이스 지향 프로그래밍입니다. 위의 인터페이스 전송 방법에는 생성자 메서드 전송과 설정자 메서드 전송이 있습니다. Spring 프레임워크를 사용해 본 사람이라면 누구나 종속성 전달 방법에 익숙할 것이라고 믿습니다.

실제 프로그래밍에서는 일반적으로 다음 세 가지 사항을 수행해야 합니다.

저수준 모듈에는 추상 클래스나 인터페이스 또는 둘 다가 있어야 합니다.

변수의 선언형은 최대한 추상 클래스나 인터페이스여야 합니다.

상속을 사용할 때는 Liskov 대체 원칙을 따르세요.

즉, 종속성 반전의 원칙에 따라 인터페이스 지향 프로그래밍을 이해하면 종속성 반전도 이해하게 됩니다.

4. 인터페이스 분리 원칙

인터페이스 분리 원칙의 의미는 단일 인터페이스를 구축하고, 거대하고 비대해진 인터페이스를 구축하지 말고, 인터페이스를 최대한 개선하려고 노력하고, 인터페이스에서 가능한 한 적은 수의 메소드를 사용하려고 노력하십시오. 즉, 호출에 의존하는 모든 클래스에 대해 거대한 인터페이스를 구축하려고 하기보다는 각 클래스에 대한 전용 인터페이스를 구축해야 합니다. 프로그래밍에서는 하나의 포괄적인 인터페이스에 의존하는 것보다 여러 특수 인터페이스에 의존하는 것이 더 유연합니다. 인터페이스는 설계 과정에서 외부적으로 설정된 "계약"입니다. 여러 인터페이스를 분산 정의함으로써 외부 변경 사항의 확산을 방지하고 시스템의 유연성과 유지 관리성을 향상시킬 수 있습니다.

이렇게 말하면 많은 사람들은 인터페이스 격리 원칙이 단일 책임 원칙과 매우 유사하다고 생각하지만 그렇지 않습니다. 첫째, 단일 책임 원칙은 원래 책임에 중점을 두었지만 인터페이스 격리 원칙은 인터페이스 종속성 격리에 중점을 두었습니다. 둘째, 단일 책임 원칙은 주로 클래스를 제한하고 인터페이스와 메소드를 제한하며 프로그램의 구현과 세부 사항을 대상으로 하는 반면, 인터페이스 격리 원칙은 주로 추상화 및 전체 프레임워크 구성을 위해 인터페이스를 제한합니다. 프로그램.

인터페이스 격리 원칙을 사용하여 인터페이스를 제한하는 경우 다음 사항에 주의하세요.

1. 인터페이스를 최대한 작게 유지하되 한도 내에서 유지하세요. 인터페이스를 개선하면 프로그래밍 유연성을 높일 수 있다는 것은 사실이지만 너무 작으면 인터페이스가 너무 많아지고 디자인이 복잡해집니다. 그러므로 적당히 이루어져야합니다.

2. 인터페이스에 의존하는 클래스에 대해 서비스를 사용자 정의하여 호출 클래스에 필요한 메서드만 노출하고 필요하지 않은 메서드는 숨깁니다. 모듈에 대한 맞춤형 서비스 제공에 집중해야만 종속성을 최소화할 수 있습니다.

3. 결속력을 높이고 외부 상호작용을 줄입니다. 인터페이스에서 가장 적은 메서드를 사용하여 가장 많은 작업을 수행하도록 합니다.

인터페이스 격리 원칙을 적용할 때 인터페이스를 너무 크거나 작게 디자인하는 것은 좋지 않습니다. 인터페이스를 디자인할 때 생각하고 계획하는 데 더 많은 시간을 투자해야만 이 원칙을 정확하게 구현할 수 있습니다.

4. 조합/집합 재사용 원칙

재사용 목적을 달성하기 위해서는 상속관계 대신 합성과 집합을 최대한 활용해야 한다는 뜻이다
이 원칙은 새 개체 만들기 기존 개체 중 일부를 내부에서 사용하여 새 개체의 일부로 만듭니다. 새 개체는 이러한 개체에 위임하여 기존 기능을 재사용하는 목적을 달성합니다.
사실 여기서 마지막은 'has-a'와 'is-a'의 차이를 구별하는 것입니다. 구성 및 집합과 비교할 때
상속의 단점은 상위 클래스의 모든 메서드가 하위 클래스에 노출된다는 것입니다. 상위 클래스가 변경되면 하위 클래스도 변경되어야 합니다. 집계를 재사용하면 다른 클래스에 대한 의존도가 줄어듭니다. .
합성/집계 재사용
① 장점:
새 객체가 구성 요소 객체에 액세스하는 유일한 방법은 구성 요소 객체의 인터페이스를 통하는 것입니다.
이러한 종류의 재사용은 내부 항목을 사용하기 때문에 블랙박스 재사용입니다.

이러한 종류의 재사용은 패키징을 지원합니다.
이런 종류의 재사용에는 더 적은 종속성이 필요합니다.
각 새 클래스는 하나의 작업에 집중할 수 있습니다. > 이러한 재사용은 런타임 시 동적으로 수행될 수 있으며, 새 객체는 구성/집계 관계를 사용하여 적절한 객체에 새로운 책임을 위임할 수 있습니다.
② 단점:
이런 방식으로 재사용을 통해 구축된 시스템은 관리할 개체가 더 많아집니다.

상속 재사용

① 장점:
기본 클래스의 대부분의 함수는 상속 관계를 통해 파생 클래스에 자동으로 들어갈 수 있으므로 새로운 구현이 더 쉽습니다. 구현하기가 더 쉽습니다.
② 단점:
상속은 기본 클래스의 구현 세부 정보를 파생 클래스에 노출시키기 때문에 상속 재사용은 패키징을 파괴합니다.
기본 클래스의 구현인 경우; 클래스가 변경되면 파생 클래스의 구현도 변경되어야 합니다.
기본 클래스에서 상속된 구현은 정적이며 런타임에 변경할 수 없으며 충분히 유연하지 않습니다.
6. 데메테르의 법칙

클래스 간의 느슨한 결합을 강조하는 것이 법칙의 기본 아이디어입니다. 약결합 클래스가 수정되면 관련 클래스에 영향을 주지 않습니다. 즉, 정보 숨기기는 소프트웨어 재사용을 촉진합니다.

프로그래밍을 접한 이후로 우리는 소프트웨어 프로그래밍의 일반 원칙인 낮은 결합과 높은 응집력을 알고 있습니다. 프로세스 지향 프로그래밍이든 객체 지향 프로그래밍이든 모듈 간의 결합을 최대한 낮게 유지해야만 코드 재사용률을 높일 수 있습니다. 낮은 결합도의 장점은 자명합니다. 그런데 프로그래밍을 통해 어떻게 낮은 결합도를 달성할 수 있을까요? 이것이 바로 데메테르의 법칙이 달성하려는 목적입니다.

데메테르의 법칙은 가장 잘 알려지지 않은 원리라고도 불리며 1987년 미국 노스이스턴 대학교의 이언 홀랜드(Ian Holland)가 처음 제안했습니다. 평신도의 관점에서 보면 클래스가 자신이 의존하는 클래스에 대해 덜 알수록 좋습니다. 즉, 종속 클래스의 경우 로직이 아무리 복잡하더라도 로직은 최대한 클래스 내부에 캡슐화되어야 하며, 제공되는 퍼블릭 메소드 외에는 어떠한 정보도 외부로 유출되지 않습니다. 데메테르의 법칙은 더 간단하게 정의됩니다. 직접적인 친구하고만 소통하세요. 먼저 직접적인 친구가 무엇인지 설명하겠습니다. 각 객체는 다른 객체와 결합 관계를 갖습니다. 두 객체 사이에 결합 관계가 있는 한 두 객체는 ​​친구라고 합니다. 의존성, 연관, 결합, 집합 등과 같은 결합 방법에는 여러 가지가 있습니다. 그 중 멤버 변수, 메소드 매개변수, 메소드 반환 값에 나타나는 클래스를 다이렉트 프렌드라고 부르지만, 지역 변수에 나타나는 클래스는 다이렉트 프렌드가 아닙니다. 즉, 익숙하지 않은 클래스가 클래스 내부에 지역 변수로 나타나지 않는 것이 가장 좋습니다.

한 문장으로 요약하자면, 객체는 다른 객체에 대해 최소한의 지식을 유지해야 합니다.

7. 단일 책임 원칙

정의: 클래스 변경에 대한 이유는 두 가지 이상입니다. 평신도의 관점에서 볼 때, 클래스는 하나의 책임만 담당하며, 변경 이유도 하나여야 합니다.

단일 책임 원칙에 관해서는 많은 사람들이 이를 무시합니다. 너무 단순하기 때문이죠. 경험이 적은 프로그래머라도 디자인 패턴을 읽은 적이 없거나 단일 책임 원칙에 대해 들어 본 적이 없더라도 소프트웨어를 디자인할 때 이 중요한 원칙은 상식이기 때문에 의식적으로 이를 준수할 것입니다. 소프트웨어 프로그래밍에서는 어느 누구도 하나의 기능을 수정하여 다른 기능이 오작동하는 것을 원하지 않습니다. 이 문제를 피하는 방법은 단일 책임 원칙을 따르는 것입니다. 단일 책임 원칙은 매우 간단하고 상식으로 간주되지만, 숙련된 프로그래머가 작성한 프로그램에도 이 원칙을 위반하는 코드가 있을 수 있습니다. 왜 이런 일이 발생합니까? 책임이 늘어나기 때문이죠. 소위 책임의 확산은 어떤 이유로 책임 P가 더 세분화된 책임 P1과 P2로 나누어지는 것을 의미합니다.

단일 책임 원칙을 따르는 장점은 다음과 같습니다.

1. 클래스는 하나의 책임만 담당하며 그 논리는 확실히 클래스의 복잡성을 줄일 수 있습니다.

2. 클래스의 가독성을 높이고 시스템의 유지 관리성을 향상합니다.

3. 단일 책임이 불가피한 경우. 원칙을 잘 따르면 하나의 기능을 수정하면 다른 기능에 미치는 영향을 크게 줄일 수 있습니다.

설명해야 할 한 가지는 단일 책임 원칙이 객체 지향 프로그래밍에만 국한된 것이 아니라는 점입니다. 모듈식 프로그래밍이라면 이 중요한 원칙을 따라야 합니다.


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.