원격 외관. PHP의 외관 디자인 패턴 외관 디자인 패턴




원격 파사드에 대한 설명

네트워킹 효율성을 향상시키기 위해 객체 메서드 집합에 대한 공통 통합 인터페이스를 제공합니다.

객체지향 모델의 Remote Facade 패턴은 작은 메소드를 가진 작은 객체에 대한 작업을 향상시킵니다. 작은 기술은 행동을 제어 및 변경하고 애플리케이션에 대한 고객의 이해를 향상시킬 수 있는 큰 기회를 제공합니다. 이러한 세분화된 동작의 한 가지 결과는 일반적으로 많은 메소드 호출을 통해 객체 간에 많은 상호 작용이 있다는 것입니다.

하나의 주소 공간에서는 "세밀한" 상호 작용이 잘 작동하지만 프로세스 간에 상호 작용이 발생하면 모든 것이 변경됩니다. 원격 통화는 많은 작업을 수행해야 하기 때문에 비용이 더 많이 듭니다. 때로는 데이터를 정리하고 보안을 확인해야 하며 패킷을 스위치에서 라우팅해야 합니다. 두 가지 프로세스가 세상의 서로 다른 끝에서 작동한다면 빛의 속도도 중요한 역할을 할 수 있습니다. 엄연한 사실은 모든 프로세스 간 통신이 프로세스 내 호출보다 훨씬 더 낭비적이라는 것입니다. 두 프로세스가 모두 동일한 시스템에서 실행되는 경우에도 마찬가지입니다. 게으른 최적화 애호가라도 이러한 성능 영향을 간과할 수 없습니다.

결과적으로 원격과 관련된 모든 개체에는 작업을 수행하는 데 필요한 요청 수를 최소화하는 보다 일반적인 인터페이스가 필요합니다. 이는 메소드뿐만 아니라 객체에도 영향을 미칩니다. 송장과 모든 항목을 별도로 요청하는 대신 한 번의 요청으로 모든 송장 항목을 읽고 업데이트해야 합니다. 이는 개체의 전체 구조에 영향을 미칩니다. 우리는 작은 객체와 작은 메소드의 좋은 목적을 잊어야 합니다. 프로그래밍이 점점 더 어려워지고 생산성이 떨어지고 떨어집니다.

원격 파사드 패턴은 보다 "세밀한" 객체 구조 위에 일반적인 "파사드"(GoF에 따름)를 나타냅니다. 이들 객체 중 어느 것도 원격 인터페이스를 갖고 있지 않으며, Remote Facade에는 어떠한 비즈니스 로직도 포함되어 있지 않습니다. Remote Facade가 하는 일은 일반 요청을 하위 개체에 대한 작은 요청 집합으로 변환하는 것뿐입니다.

Facade 패턴의 목적

  • Facade 패턴은 하위 시스템 인터페이스 세트 대신 통합 인터페이스를 제공합니다. Facade는 하위 시스템을 더 쉽게 사용할 수 있도록 하는 상위 수준 인터페이스를 정의합니다.
  • Facade 패턴은 복잡한 하위 시스템을 더 간단한 인터페이스로 래핑합니다.

해결해야 할 문제

고객은 복잡한 하위 시스템의 전체 기능에 대한 단순화된 인터페이스를 원합니다.

Facade 패턴에 대한 토론

Facade 패턴은 복잡한 하위 시스템을 단일 인터페이스 객체로 캡슐화합니다. 이는 하위 시스템을 학습하는 데 걸리는 시간을 줄이고 하위 시스템과 잠재적으로 많은 수의 클라이언트 간의 결합 정도를 줄이는 데도 도움이 됩니다. 반면, 파사드가 하위 시스템에 대한 유일한 액세스 지점인 경우 고급 사용자에게 필요할 수 있는 기능이 제한됩니다.

중재 기능을 구현하는 Facade 객체는 상당히 단순하게 유지되어야 하며 모든 것을 아는 "오라클"이 되어서는 안 됩니다.

외관 패턴 구조

클라이언트는 Facade를 통해 하위 시스템과 통신합니다. 클라이언트로부터 요청이 수신되면 Facade 객체는 이를 원하는 하위 시스템 구성 요소로 전달합니다. 클라이언트의 경우 하위 시스템의 구성 요소는 "어둠에 가려진 미스터리"로 남아 있습니다.

SubsystemOne 및 SubsystemThree 하위 시스템은 SubsystemTwo 하위 시스템의 내부 구성 요소와 직접 상호 작용하지 않습니다. SubsystemTwoWrapper "facade"(즉, 더 높은 수준의 추상화)를 사용합니다.

Facade 패턴은 하위 시스템에 대한 통합된 상위 수준 인터페이스를 정의하여 사용을 더 쉽게 만듭니다. 구매자는 전화로 카탈로그 제품을 주문할 때 정면에 직면하게 됩니다. 구매자는 고객 서비스에 전화하여 구매하려는 품목을 나열합니다. 서비스 담당자는 이행 부서, 판매 부서 및 배송 서비스에 대한 인터페이스를 제공하는 "프론트" 역할을 합니다.

  • 하위 시스템에 대한 간단하고 통합된 인터페이스를 정의합니다.
  • 하위 시스템을 캡슐화하는 "래퍼" 클래스를 디자인합니다.
  • 하위 시스템의 전체 복잡성과 해당 구성 요소의 상호 작용은 클라이언트에게 숨겨집니다. "façade"/"wrapper"는 사용자 요청을 적절한 하위 시스템 메서드로 전달합니다.
  • 클라이언트는 "façade"만 사용합니다.
  • 추가 "외관"을 만드는 가능성을 고려하십시오.

외관 패턴의 특징

  • Facade는 새로운 인터페이스를 정의하고 Adapter는 기존 인터페이스를 사용합니다. Adapter는 새 인터페이스를 만들지 않고도 두 개의 기존 인터페이스가 함께 작동하도록 만든다는 점을 기억하세요.
  • Flyweight가 많은 작은 개체를 만드는 방법을 보여주는 반면 Facade는 전체 하위 시스템을 나타내는 단일 개체를 만드는 방법을 보여줍니다.
  • Mediator는 기존 클래스의 기능을 추상화한다는 점에서 Facade와 유사합니다. 그러나 중재자는 둘 중 하나에 고유하지 않은 피어 개체 간의 기능을 중앙 집중화합니다. 동료들은 Mediator를 통해 서로 정보를 교환합니다. 반면 Facade는 서브시스템에 대한 간단한 인터페이스를 정의하고 새로운 기능을 추가하지 않으며 서브시스템의 클래스에 알려지지 않습니다.
  • Abstract Factory는 Facade의 대안으로 사용되어 플랫폼별 클래스를 숨길 수 있습니다.
  • "Facade" 객체는 하나의 Facade 객체만 필요하기 때문에 싱글톤인 경우가 많습니다.
  • Adapter와 Facade는 모두 래퍼이지만 서로 다른 유형의 래퍼입니다. Facade의 목표는 더 간단한 인터페이스를 만드는 것이고, Adapter의 목표는 기존 인터페이스를 조정하는 것입니다. Facade는 일반적으로 여러 객체를 래핑하고 Adapter는 하나의 객체를 래핑합니다.

Facade 패턴 구현

시스템을 구성 요소로 나누면 복잡성이 줄어듭니다. Facade 패턴을 사용하면 시스템 구성 요소 간의 연결을 느슨하게 할 수 있습니다. façade 객체는 시스템 구성요소에 대한 단순화된 단일 인터페이스를 제공합니다.

아래 예는 네트워크 서비스 시스템을 모델링합니다. FacilityFacade는 시스템의 내부 구조를 숨깁니다. 사용자는 한번 서비스를 요청한 후, 5개월 동안 주 1~2회 요청한 서비스가 완료될 때까지 작업 진행 상황을 문의합니다.

#포함하다 class MisDepartment ( public: void submitNetworkRequest() ( _state = 0; ) bool checkOnStatus() ( _state++; if (_state == Complete) return 1; return 0; ) private: enum States ( 수신, DenyAllKnowledge, ReferClientToFacilities, FacilityHasNotSentPaperwork, ElectricianIsNotDone , 전기 기사DidItWrong, 파견 기술자, SignedOff, DoesNotWork, 전기 기사 배선 수정, 완료 ); class ElectricianUnion ( public: void submitNetworkRequest() ( _state = 0; ) bool checkOnStatus() ( _state++; if (_state == Complete) return 1; return 0; ) private: enum States ( 수신, RejectTheForm, SizeTheJob, SmokeAndJokeBreak, WaitForAuthorization , DoTheWrongJob, BlameTheEngineer, WaitToPunchOut, DoHalfAJob, ComplainToEngineer, GetClarification, CompleteTheJob, TurnInThePaperwork, 완료 ); class FacilityDepartment ( public: void submitNetworkRequest() ( _state = 0; ) bool checkOnStatus() ( _state++; if (_state == Complete) return 1; return 0; ) private: enum States ( 수신, AssignToEngineer, EngineerResearches, RequestIsNotPossible, EngineerLeavesCompany , AssignToNewEngineer, NewEngineerResearches, ResignEngineer, EngineerReturns, EngineerResearchesAgain, EngineerFillsOutPaperWork, 완료 ); class FacilityFacade ( public: FacilityFacade() ( _count = 0; ) void submitNetworkRequest() ( _state = 0; ) bool checkOnStatus() ( _count++; /* 서비스 요청 수신됨 */ if (_state == 수신됨) ( _state++; / * 요청을 엔지니어에게 리디렉션 */ _engineer.submitNetworkRequest();<< "submitted to Facilities - " << _count << " phone calls so far" << endl; } else if (_state == SubmitToEngineer) { /* Если инженер свою работу выполнил, перенаправим запрос электрику */ if (_engineer.checkOnStatus()) { _state++; _electrician.submitNetworkRequest(); cout << "submitted to Electrician - " << _count << " phone calls so far" << endl; } } else if (_state == SubmitToElectrician) { /* Если электрик свою работу выполнил, перенаправим запрос технику */ if (_electrician.checkOnStatus()) { _state++; _technician.submitNetworkRequest(); cout << "submitted to MIS - " << _count << " phone calls so far" << endl; } } else if (_state == SubmitToTechnician) { /* Если техник свою работу выполнил, то запрос обслужен до конца */ if (_technician.checkOnStatus()) return 1; } /* Запрос еще не обслужен до конца */ return 0; } int getNumberOfCalls() { return _count; } private: enum States { Received, SubmitToEngineer, SubmitToElectrician, SubmitToTechnician }; int _state; int _count; FacilitiesDepartment _engineer; ElectricianUnion _electrician; MisDepartment _technician; }; int main() { FacilitiesFacade facilities; facilities.submitNetworkRequest(); /* Звоним, пока работа не выполнена полностью */ while (!facilities.checkOnStatus()) ; cout << "job completed after only " << facilities.getNumberOfCalls() << " phone calls" << endl; }

프로그램 출력:

시설에 제출됨 - 지금까지 전기 기술자에게 제출된 1개의 전화 통화 - 지금까지 MIS에 제출된 12개의 전화 통화 - 지금까지 25개의 전화 통화 단 35개의 전화 통화 후에 작업이 완료되었습니다.

2010년 3월 11일 10:30

디자인 패턴 "Facade" / "Facade"

  • 완벽한 코드

다른 패턴에 대한 설명입니다.

문제

일부 복잡한 시스템의 하위 시스템 의존성과 하위 시스템 간의 정보 교환을 최소화합니다.

설명

복잡한 시스템을 설계할 때 소위 말하는 복잡한 시스템을 더 작고 단순한 하위 시스템으로 분해하는 분해의 원리. 또한 분해 수준(깊이)은 전적으로 설계자에 의해 결정됩니다. 이러한 접근 방식 덕분에 개별 시스템 구성 요소를 개별적으로 개발한 다음 함께 통합할 수 있습니다. 그러나 언뜻 보면 시스템 모듈의 높은 연결성 문제가 발생합니다. 이는 무엇보다도 모듈이 서로 교환하는 많은 양의 정보에서 나타납니다. 또한 이러한 통신을 위해서는 일부 모듈에는 다른 모듈의 특성에 대한 충분한 정보가 있어야 합니다.

따라서 하위 시스템의 종속성을 최소화하고 하위 시스템 간에 전송되는 정보의 양을 줄이는 것이 주요 설계 작업 중 하나입니다.

이 문제를 해결하는 한 가지 방법은 "Facade" 패턴을 사용하는 것입니다.

Façade 패턴은 하위 시스템 인터페이스 세트 대신 통합 인터페이스를 제공합니다. Façade는 다음과 같은 상위 수준 인터페이스를 정의합니다.
이는 하위 시스템의 사용을 단순화합니다.

간단히 말해서, "Facade"는 복잡한 하위 시스템과 함께 작업하기 위한 높은 수준의 작업 집합을 축적하는 개체에 지나지 않습니다. Facade는 이 하위 시스템의 기능을 구현하는 클래스를 집계하지만 숨기지 않습니다. 물론 클라이언트가 필요할 경우 하위 시스템 클래스에 대한 하위 수준 액세스 권한이 박탈되지 않는다는 점을 이해하는 것이 중요합니다. Façade는 하위 시스템의 특정 작업을 단순화하지만 클라이언트에 해당 사용을 강요하지는 않습니다.

실제적인 문제

"Facade" 패턴을 사용하여 일부 사용자 인증 하위 시스템에 대한 통합 인터페이스를 구현합니다. 이 예에서 인증 하위 시스템 자체는 "복잡한 시스템"인 척하지 않지만 패턴의 주요 장점을 명확하게 반영합니다.

클래스 다이어그램

다이어그램을 살펴 보겠습니다. 명확성을 위해 인증 하위 시스템의 프레임워크는 직사각형으로 강조 표시되어 있습니다. Authorizator 외관은 클라이언트에게 하위 시스템 작업을 위한 통합 인터페이스를 제공합니다. 이 경우에는 Authorize()라는 메서드가 하나만 있지만 더 있을 수도 있습니다. 이 경우 클라이언트는 파사드를 사용하여 서브시스템과 작업하거나 이를 구성하는 클래스를 직접 사용할 수 있습니다. 인증 과정 자체는 매우 간단합니다. 사용자 이름을 기준으로 데이터베이스의 해당 항목이 DB 인터페이스를 통해 검색됩니다. 그런 다음 찾은 항목의 비밀번호와 사용자가 지정한 비밀번호를 비교합니다.

C#으로 구현

구현 코드에서 아니요클래스 PgSQLDB.
시스템 사용;
System.Collections.Generic 사용;
System.Linq 사용;
System.Text 사용;
System.Security 사용;

네임스페이스 파사드
{
//추상 사용자 클래스
추상 클래스 사용자
{
보호된 문자열 사용자 이름;
보호된 문자열 비밀번호;

공개 추상 문자열 getUserRole();

공개 문자열 getPasswdHash()
{
// 이 줄은 의미론적 의미를 지니지 않습니다.
// 물론 이는 안전하지 않은 비밀번호 해시를 제공합니다.
return passwd.GetHashCode().ToString();
}
}

// 사용자를 기본 사용자로 지정
클래스 DefaultUser: 사용자
{
공개 DefaultUser(문자열 사용자 이름, 문자열 비밀번호)
{
this .username = 사용자 이름;
이 .passwd = 비밀번호;
}


{
"DEFAULT_USER"를 반환합니다.
}
}

// 사용자를 관리자로 지정
클래스 관리자: 사용자
{
공용 관리자(문자열 사용자 이름, 문자열 비밀번호)
{
this .username = 사용자 이름;
이 .passwd = 비밀번호;
}

공개 재정의 문자열 getUserRole()
{
"관리자"를 반환합니다.
}

// 데이터베이스 액세스 인터페이스
인터페이스 DB
{
사용자 검색(문자열 사용자 이름);
}

// SQLite용 데이터베이스 인터페이스 구현
클래스 SQLiteDB:DB
{
공개 SQLiteDB(문자열 파일 이름)
{
// 데이터베이스 드라이버 초기화
}

공개 사용자 검색(문자열 사용자 이름)
{
// 스텁
새로운 NotImplementedException()을 던져라;
}
}

// 사용자 인증
공개 무효 승인(문자열 사용자 이름, 문자열 비밀번호)
{
DB db = new SQLiteDB("db.sqlite" );
사용자 user = db.search(사용자명);
if (user.getPasswdHash() == 비밀번호)
{
// 모든 것이 정상입니다. 사용자가 인식됩니다.
}
또 다른
{
// 문제가 발생했습니다.
throw new SecurityException("비밀번호 또는 사용자 이름이 잘못되었습니다!" );
}
}
}

수업 프로그램
{
정적 무효 Main(문자열 인수)
{
// 가상의 사용자
문자열 사용자 이름 = "Vasya" ;
string passwd = "qwerty" .GetHashCode().ToString();

승인자 인증 = new Authorizer();
노력하다
{
auth.authorize(사용자 이름, 비밀번호);
}
잡기 (SecurityException ex)
{
// 사용자가 인증되지 않았습니다.
}
}
}
}


* 이 소스 코드는 소스 코드 하이라이터로 강조 표시되었습니다.

추신: 하브라에디터가 작동하지 않는 건 저뿐인가요?

읽기 전에 다음 규칙과 개념을 검토하십시오. 이 글은 일정한 빈도로 업데이트되므로, 이전에 읽어보셨다면 데이터가 변경되지 않았다는 것은 사실이 아닙니다.

정면클래스에 속한다 구조적패턴. 특정 하위 시스템의 인터페이스 집합이 아닌 통합 인터페이스를 나타냅니다. Façade 패턴은 하위 시스템을 더 쉽게 사용할 수 있도록 하는 상위 수준 인터페이스를 정의합니다.

복잡한 시스템을 하위 시스템으로 나누면 설계 프로세스가 단순화되고 한 하위 시스템이 다른 하위 시스템에 대한 종속성을 최소화하는 데에도 도움이 됩니다. 그러나 이는 이러한 하위 시스템을 함께 사용하는 것이 상당히 어렵다는 사실로 이어집니다. 이 문제를 해결하는 한 가지 방법은 파사드 패턴을 도입하는 것입니다.

이는 특정 시스템에 따라 다르기 때문에 명확한 구현이 없는 패턴 중 하나입니다. 일반적으로 다음 변환을 수행해야 합니다.

회색 직사각형에는 하위 시스템이 포함되어 있으며, 하위 시스템에는 서로 종속성이 있습니다(그렇지 않을 수도 있음). 상위 3개 블록은 이 하위 시스템과 상호 작용하는 클라이언트 코드의 3개 섹션을 나타냅니다. 우리의 임무는 하위 시스템과 상호 작용하기에 충분한 간단하고 통합된 인터페이스를 만드는 것입니다. 작업의 틀 내에서,저것들. 모든 경우에 대해 범용 인터페이스를 만들 필요는 없습니다. 대부분의 경우 이는 불필요하고 상호 작용이 더 복잡해지고 개발 시간이 늘어나기 때문입니다.

다음은 한 가지 구현의 스케치입니다.

/** * SystemA */ 클래스 Bank ( 공용 함수 OpenTransaction() () 공용 함수 CloseTransaction() () 공용 함수 transferMoney($amount) () ) /** * SystemB */ 클래스 클라이언트 ( 공용 함수 OpenTransaction() ( ) 공용 함수 CloseTransaction() () 공용 함수 transferMoney($amount) () ) /** * SystemC */ class Log ( 공용 함수 logTransaction() () ) class Facade ( 공용 함수 transfer($amount) ( $Bank = new Bank(); $Client = new Log(); Bank->transferMoney(-$amount); $Log->logTransaction("은행에서 자금 이체") ->CloseTransaction(); ; $Log->logTransaction("Transaction close" ) ) // 클라이언트 코드 $Transfer = new Facade(); $이체->이체(1000);

정면.

유형

구조적 디자인 패턴.

설명

Facade 패턴은 하나의 특수 인터페이스 아래에 개체 그룹을 결합하고 해당 개체에 대한 메서드 호출을 전달합니다.

필요한 경우 템플릿이 사용됩니다.

  • 복잡한 시스템에 대한 액세스를 단순화합니다.
  • (또는) 시스템에 대한 다양한 수준의 액세스를 생성합니다.
  • (또는) 시스템과 클라이언트 간의 종속성 수를 줄입니다.

먼저 명확히 해야 할 점은 템플릿이 제공하는 인터페이스가 시스템에 포함된 객체의 모든 메소드를 합한 것이 아니라는 점이다. 이러한 일반화된 버전을 만들면 "신성한 인터페이스"가 출현하게 됩니다. 저것들. 명확하게 정의된 목적이 없고 많은 수의 종속성을 생성하지 않고 수많은 메서드가 있는 인터페이스입니다. 결과는 패턴과 정반대입니다.

Facade의 목적은 특정 문제를 해결하기 위한 방법을 포함하거나 소스 시스템의 특정 추상화를 제공하는 인터페이스를 생성하는 것입니다. 다음이 가능합니다:

  • 템플릿 인터페이스 호출을 시스템 개체로 리디렉션합니다.
  • 미리 결정된 값을 대체하여 방법 매개변수의 수를 줄이는 단계;
  • 시스템 개체에 대한 호출을 결합하거나 자체 논리를 추가하는 새로운 메서드를 생성합니다.
  • 원래 메서드와 속성 중 일부는 Facade를 통해 사용할 수 없습니다. 문제 해결에 역할을 하지 않습니다.

이 접근 방식은 복잡한 시스템의 사용을 단순화합니다. 동시에 호출되는 메서드 수와 총 호출 수가 줄어듭니다. 그 결과 애플리케이션의 종속성 수가 감소합니다.

Facade에서는 시스템에서 사용하는 객체를 숨길 필요가 없다는 점에 유의하는 것이 중요합니다. 그러나 한 가지 중요한 조건이 있습니다. Façade 인터페이스가 생성된 클라이언트 부분은 해당 인터페이스만 사용해야 하며 시스템 개체에 직접 액세스해서는 안 됩니다. 이는 클라이언트의 작업을 인터페이스에 보다 정확하게 반영하는 데 도움이 됩니다.

또한 시스템은 다양한 유형의 문제를 해결하기 위해 여러 Facade를 제공할 수 있습니다. 이를 통해 서로 위에 있거나 동일한 평면에 위치할 수 있는 여러 수준의 추상화를 만들 수 있습니다. 클라이언트는 작업에 특정 Facade를 사용하거나 특정 개체를 직접 작업할 수 있습니다.

흥미로운 옵션은 Façade와 Abstract Factory 템플릿을 함께 사용하는 것입니다. 이 경우 Façade 인터페이스는 객체 자체가 아니라 해당 인터페이스와 연관됩니다. 이는 구현을 숨기고 추상 팩토리에 이를 변경할 수 있는 기능을 제공합니다. 예를 들어, 이 접근 방식은 시스템이 플랫폼 또는 하드웨어 종속 클래스를 사용할 때 찾을 수 있습니다.

유사한 패턴과 차이점

정면 하나의 특수 인터페이스 아래에 개체 그룹을 통합합니다. 이는 객체 그룹 작업을 단순화하고 새로운 수준의 추상화를 도입합니다. 특수 인터페이스를 구현하는 데 필요한 개체를 포함하거나 참조합니다.
어댑터 기능을 변경하지 않고 개체의 인터페이스를 변경합니다. 여러 개체를 하나의 인터페이스에 적용할 수 있습니다. 기존 코드를 재사용할 수 있습니다. 적응형 개체를 포함하거나 상속합니다.
다리 객체를 추상화와 구현으로 분리합니다. 개체 계층 구조에 사용됩니다. 추상화와 구현을 별도로 변경(상속)하여 시스템의 유연성을 높일 수 있습니다. 지정된 추상화 및 해당 구체화(상속자)에 대한 메서드를 제공하는 개체(구현)를 포함합니다.
데코레이터 개체의 기능을 확장하고 해당 동작을 변경합니다. 장식 가능한 개체 인터페이스를 지원하지만 새로운 메서드와 속성을 추가할 수 있습니다. 개체의 기능을 동적으로 변경할 수 있습니다. 이는 상속(다중 포함)의 대안입니다. 장식할 개체가 포함되어 있습니다. 순차적으로 호출되는 객체 체인이 가능합니다.
대리 객체를 투명하게 대체하고 객체에 대한 액세스를 제어합니다. 인터페이스나 동작을 변경하지 않습니다. 개체 작업을 단순화하고 최적화합니다. 자체 기능을 추가하여 클라이언트로부터 숨길 수 있습니다. 객체 또는 이에 대한 참조를 포함하며 대체된 객체의 존재를 제어할 수 있습니다.
링커 복합 개체 및 해당 부분과 상호 작용하기 위한 단일 인터페이스를 제공합니다. 이를 통해 고객의 작업이 단순화되고 복합 개체 및 해당 부품의 새로운 변형을 쉽게 추가할 수 있습니다. 복합 개체 및 해당 부품에 인터페이스로 포함됩니다.
기회주의자

객체의 인터페이스를 변경하는 것을 목표로 하지 않습니다. 그러나 이는 추출된 상태 부분에서 데이터를 다시 가져오는 데 필요할 수 있습니다.

애플리케이션의 개체 인스턴스 수를 줄여 리소스를 절약할 수 있습니다. 개체 상태의 상황에 맞는 부분을 외부화하여 개체의 여러 인스턴스를 하나로 바꿉니다.

여러 가지 적응 가능한 객체를 사용하는 두 가지 매우 유사한 패턴인 Facade와 Adapter에 별도로 초점을 맞춰 보겠습니다. 질문이 발생할 수 있습니다. 차이점은 무엇입니까? 그들의 목표에 주의를 기울이십시오. 기존 인터페이스를 구현하고 코드를 재사용하기 위해 개체의 공용체를 사용하는 경우 이는 어댑터입니다. 작업의 본질을 강조하고, 작업을 단순화하며, 새로운 인터페이스의 출현은 모두 Façade의 징후입니다.

그런데 실제 상황에서는 '유사성'이 아닌 목표에 따라 템플릿을 적용해야 합니다. 그러므로 그러한 질문은 공부 중에만 발생할 수 있습니다.

일반적인 형태로 템플릿 구현

템플릿 구현에는 다음과 같은 접근 방식이 가능합니다.

  1. 시스템의 인스턴스를 참조하는 별도의 클래스를 만듭니다. 이는 고전적인 옵션이며 구현이 명확하게 강조됩니다. 별도의 개체입니다. public class FacadeImpl: IFacade ( private AppSubSystem _system; public FacadeImpl(AppSubSubSystem s) ( this._system = s; ) /* Skipped */ ) 또한 Facade 내부에 시스템 인스턴스를 생성할 수 있습니다: public class FacadeImpl: IFacade ( private readonly AppSubSystem _system = new AppSubSystem() /* 생략됨 */ )
  2. 시스템에 Facade 인터페이스를 추가합니다. Façade에 많은 클라이언트가 있고 각 클라이언트를 템플릿 구현의 자체 인스턴스로 생성할 필요가 없는 경우 유용할 수 있습니다. 공용 클래스 AppSubSystem ( 공용 IFacade FacadeInterface ( get; 개인 세트; ) 공용 AppSubSystem () ( this.FacadeInterface = new FacadeImpl(this); ) /* 건너뛰기 */ )
  3. 상속을 사용하여 시스템 클래스 자체에서 Facade 인터페이스를 지원합니다. 구현은 시스템 전체에서 "흐릿한" 것으로 나타났습니다. 그러나 이제 Façade 인터페이스가 필요한 곳에서 해당 인스턴스를 사용할 수 있습니다. 또한 시스템의 비공개 필드와 메서드에 액세스하는 것이 가능해지며 호출을 동일한 메서드로 리디렉션할 필요가 없습니다. 공용 클래스 AppSubSystem: IFacade( /* 건너뛰기 */ )

이러한 접근 방식은 모두 다음과 같이 작성할 수 있습니다.

  • 선택한 작업 또는 새로운 추상화의 기능을 결정합니다.
  • 우리는 이를 시스템의 기존 개체와 조정합니다.
  • 템플릿 인터페이스 개발 ;
  • 우리는 구현할 것이다 옵션 중 하나에서:
    • 시스템 개체에 대한 호출을 리디렉션하는 별도의 클래스입니다.
    • 시스템 자체의 클래스에서;
  • 클라이언트는 여러 클래스와 상호 작용하는 대신 하나의 새로운 인터페이스로 작업합니다.

구현예

콘텐츠 관리 시스템 내에서 간단한 블로그 게시물 편집기를 만드는 예를 살펴보겠습니다. 이 하위 시스템에 포함될 개체를 나열해 보겠습니다. 간결함을 위해 예제에 필수적이지 않은 승인 및 기타 방법을 제거하겠습니다.

기본부터 시작해 보겠습니다. 수업에서 제출한 블로그 게시물입니다. 블로그 게시물.이 클래스는 단일 레코드의 속성과 콘텐츠를 저장합니다.

공개 클래스 BlogPost( ///

게시물 속성을 가져오거나 설정합니다.공개 BlogPostProperties 속성( get; set; ) /// 게시물 내용을 가져오거나 설정합니다.공개 BlogPostContent 콘텐츠( get; set; ) )

다음 수업 블로그포스트저장– 서버에 블로그 게시물을 저장합니다. 이를 통해 인증 데이터를 설정하고 기록을 다운로드 및 게시할 수 있습니다.

공용 클래스 BlogPostStorage( ///

공개 문자열 서버( get; set; ) /// 블로거의 로그인을 가져오거나 설정합니다.공개 문자열 로그인( get; set; ) /// 블로거의 비밀번호를 가져오거나 설정합니다.공개 문자열 비밀번호(개인 get; 설정; ) /// /// 시작 날짜입니다. /// 종료 날짜입니다. /// 공개 목록 GetPostList(DateTime startDate, DateTime endDate) ( /* 생략됨 */ ) /// 지정된 ID와 연결된 게시물을 가져옵니다. /// 가져올 게시물의 ID입니다. /// ID에 대한 인스턴스입니다.공개 BlogPost GetPost(int postId) ( /* 생략됨 */ ) /// 지정된 ID와 관련된 게시물을 삭제합니다. /// 삭제할 게시물의 ID입니다. public void DeletePost(int postId) ( /* 건너뛰기 */ ) /// 지정된 게시물을 게시합니다. /// 게시할 게시물입니다.공개 무효 게시(BlogPost 게시물) ( /* 건너뛰기 */ ) )

철자를 확인하는 간단한 클래스가 있습니다. SimpleSpellChecker.

공용 클래스 SimplepellChecker( ///

단어의 철자 오류를 확인합니다. /// 확인하라는 말이다. /// 이 메서드가 반환되면 /// 지정된 단어에 대한 제안이 포함됩니다. /// 올바른 단어에서는 true입니다. 그렇지 않으면 거짓 public bool Check(문자열 단어, 목록 출력 제안) ( /* 건너뛰었습니다 */ ) )

마지막 구성 요소는 텍스트 편집기입니다. 간결성을 위해 그의 방법을 거의 모두 제거하겠습니다.

공용 클래스 PostEditor( ///

맞춤법 검사기.개인 읽기 전용 SimpleSpellChecker _spellChecker = new SimpleSpellChecker(); /// public bool IsSpellCheckComplete ( get; private set; ) /// 편집할 게시물을 가져오거나 설정합니다.공개 BlogPost 게시물( get; set; ) /// 게시물 속성을 가져옵니다.공개 BlogPostProperties PostProperties ( get ( if (this.Post == null) ( return null; ) return this.Post.Properties; ) ) /// 게시물 내용을 가져옵니다.공개 BlogPostContent PostContent ( get ( if (this.Post == null) ( return null; ) return this.Post.Content; ) ) )

블로그 게시물 편집기로 넘어가겠습니다. 하위 시스템은 다음과 같습니다.

공용 클래스 BlogEditor ( 개인 읽기 전용 BlogPostStorage _storage = 새 BlogPostStorage(); 공용 BlogPostStorage 저장소 ( get ( return this._storage; ) ) 개인 읽기 전용 PostEditor _editor = 새 PostEditor(); 공용 PostEditor Editor ( get ( return this._editor; ) ) )

클라이언트는 이러한 개체를 직접 사용할 수 있습니다. 하지만 그에게 그게 필요할까? 자세히 살펴보면 다음과 같은 기능이 필요하다는 것을 알 수 있습니다.

  • 서버에 로그인하기 위한 세부 정보를 지정합니다. 섬기는 사람, 로그인, 비밀번호;
  • 항목 목록 다운로드: 포스트리스트 가져오기();
  • 편집을 위해 항목 업로드: 포스트로드();
  • 게시물 속성과 해당 텍스트를 가져옵니다. Post속성, 게시물 내용;
  • 항목의 철자가 확인되었는지 확인하세요. IsSpellCheckComplete;
  • 게시물 게시: 게시();
  • 항목 삭제: 게시물 삭제().

이 모든 것은 Facade의 인터페이스로 작성될 수 있습니다.

공용 인터페이스 IBlogEditorFacade( ///

서버 주소를 가져오거나 설정합니다.문자열 서버( get; set; ) /// 블로거의 로그인을 설정합니다.문자열 로그인 ( set; ) /// 블로거의 비밀번호를 설정합니다.문자열 비밀번호( set; ) /// 맞춤법 검사가 완료되었는지 여부를 나타내는 값을 가져옵니다. bool IsSpellCheckComplete ( get; ) /// 현재 게시물 속성을 가져옵니다. BlogPostProperties PostProperties( get; ) /// 현재 게시물 콘텐츠를 가져옵니다. BlogPostContent PostContent ( get; ) /// /// 지정된 기간 동안 서버에 게시된 게시물의 모음을 나타내는 목록을 반환합니다. /// 시작 날짜입니다. /// 종료 날짜입니다. /// 서버의 게시물 모음을 나타내는 목록입니다.목록 GetPostList(DateTime startDate, DateTime endDate); /// 지정된 게시물을 로드합니다. /// 가져올 게시물의 ID입니다. void LoadPost(int postId); /// 현재 게시물을 블로그에 게시합니다.무효 게시(); /// 지정된 게시물을 삭제합니다. /// 삭제할 게시물의 ID입니다. void DeletePost(int postId); )

이 인터페이스를 구현해 보겠습니다. 생성된 메서드와 속성은 매우 간단합니다. 그들은 단순히 요청을 시스템의 원하는 개체로 리디렉션합니다. 따라서 간결성을 위해 위의 코드를 단축하겠습니다. 생성자와 각각 하나의 속성과 하나의 메서드만 남겨두겠습니다.

공용 클래스 BlogEditorFacade: IBlogEditorFacade( 개인 BlogEditor _blogEditor; ///

///의 새 인스턴스를 초기화합니다. 수업. /// 블로그 편집기 인스턴스에 대한 참조입니다. public BlogEditorFacade(BlogEditor blogEditor) ( if (blogEditor == null) ( throw new ArgumentNullException("blogEditor can"t be null"); ) this._blogEditor = blogEditor; ) public string Server ( get ( return this._blogEditor.Storage. 서버; ) 설정 ( this._blogEditor.Storage.Server = value; ) ) public void LoadPost(int postId) ( BlogPost 게시물 = this._blogEditor.Storage.GetPost(postId); if (post != null) ( this._blogEditor .Editor.Post = post; ) ) /* IBlogEditorFacade 구현을 건너뛰었습니다 */ )

클래스 생성자는 Facade가 액세스를 제공해야 하는 시스템 인스턴스를 지정합니다. 이제 클라이언트 코드에서 인터페이스를 사용하여 더 쉽게 액세스할 수 있습니다.

공용 클래스 BlogClient( private readonly IBlogEditorFacade _blogEditor = null; public BlogClient(IBlogEditorFacade iBlogEditor)( this._blogEditor = iBlogEditor; ) public bool ValidateAndPublish()( bool isPostValid = true; BlogPostContent content = this._blogEditor.PostContent; /// TODO: (isPostValid) ( this._blogEditor.Publish(); ) return isPostValid ) )인 경우 콘텐츠 유효성을 검사합니다.

용법 블로그클라이언트다음과 같이:

BlogEditor blogEditorObject = 새로운 BlogEditor(); /// ... BlogClient blogClient = new BlogClient(new BlogEditorFacade(blogEditorObject));

인터페이스가 Facade 생성자에 전달된다는 점에 유의하세요. 또한 시스템 객체 생성( 블로그편집자) 템플릿 구현에서 제거되었습니다.

따라서 클라이언트는 시스템과 작동하기 위해 생성된 인터페이스만 사용합니다. 시스템 구현에 대한 템플릿 구현의 의존도도 감소되었습니다. 결국 사본 대신 블로그편집자그 후손에게 물려줄 수 있습니다.

그러나 어떤 경우에는 템플릿 자체 내에 개체를 만드는 것이 더 유리합니다. 예를 들어, Façade의 각 인스턴스에는 고유한 시스템 인스턴스가 있거나 필요한 경우 클라이언트에서 사용 중인 시스템을 숨길 수 있습니다.

고려 중인 예로 돌아가면 시스템과의 상호 작용이 더 쉬워졌다는 것을 알 수 있습니다. 해당 개체의 메서드 및 메서드 호출 수가 감소했습니다. 템플릿 사용 목적이 달성되었습니다.