C\#디자인 모델 시리즈 튜 토리 얼-관찰자 모드

12386 단어 C#디자인 모드
1.개술
때로는 게시/구독 모드 라 고 불 리 며 관찰자 모드 는 한 쌍 의 다 중 의존 관 계 를 정의 하여 여러 관찰자 대상 이 특정한 주제 대상 을 동시에 감청 하도록 한다.이 테마 대상 은 상태 가 변 할 때 모든 관찰자 대상 에 게 자동 으로 자신 을 업데이트 할 수 있 도록 알려 줍 니 다.
2.해결 하 는 문제
하나의 시스템 을 서로 협력 하 는 유형 으로 나 누 는 것 은 좋 지 않 은 부작용 이 있다.그것 은 바로 관련 대상 간 의 일치 성 을 유지 해 야 한 다 는 것 이다.우 리 는 일치 성 을 유지 하기 위해 각종 긴밀 한 결합 을 원 하지 않 는 다.이렇게 하면 유지,확장 과 재 활용 에 불편 을 가 져 올 수 있다.관찰 자 는 바로 이런 결합 관 계 를 해결 하 는 것 이다.
3.모드 속 캐릭터
3.1 추상 적 인 주제(Subject):모든 관찰자 대상 의 인용 을 하나의 집합 에 저장 하고 모든 주 제 는 모든 수량의 관찰자 가 있 을 수 있다.추상 적 인 테 마 는 관찰자 대상 을 추가 하고 삭제 할 수 있 는 인 터 페 이 스 를 제공 합 니 다.
3.2 구체 적 인 주제(Concrete Subject):관련 상 태 를 구체 적 인 관찰자 대상 에 저장 합 니 다.구체 적 인 주제 내부 상태 가 바 뀌 었 을 때 등 록 된 모든 관찰자 에 게 알림 을 보 냅 니 다.
3.3 추상 적 인 관찰자(Observer):모든 구체 적 인 관찰자 에 게 인 터 페 이 스 를 정의 하고 주제 알림 을 받 을 때 자신 을 업데이트 합 니 다.
3.4 구체 적 인 관찰자(ConcreteObserver):추상 적 인 관찰자 역할 이 요구 하 는 업데이트 인 터 페 이 스 를 실현 하여 자신의 상태 와 주제 상 태 를 조 화 롭 게 한다.
4.패턴 판독
4.1 관찰자 모델 의 유형 도
//img.jbzj.com/file_images/article/201606/201606010917421.png
4.2 관찰자 모드 의 코드

 /// <summary>
 ///      
 /// </summary>
 public abstract class Subject
 {
 private IList<Observer> observers = new List<Observer>();

 /// <summary>
 ///      
 /// </summary>
 /// <param name="observer"></param>
 public void Attach(Observer observer)
 {
  observers.Add(observer);
 }

 /// <summary>
 ///      
 /// </summary>
 /// <param name="observer"></param>
 public void Detach(Observer observer)
 {
  observers.Remove(observer);
 }

 /// <summary>
 ///     ( )    
 /// </summary>
 public void Notify()
 {
  foreach (Observer o in observers)
  {
  o.Update();
  }
 }
 }

 /// <summary>
 ///       ,              ,          
 /// </summary>
 public abstract class Observer
 {
 public abstract void Update();
 }

 /// <summary>
 ///            ,              ;             ,              。                 。
 /// </summary>
 public class ConcreteSubject : Subject
 {
 private string subjectState;

 /// <summary>
 ///         
 /// </summary>
 public string SubjectState
 {
  get { return subjectState; }
  set { subjectState = value; }
 }
 }

 /// <summary>
 ///      ,                 ,              
 /// </summary>
 public class ConcreteObserver : Observer
 {
 private string observerState;
 private string name;
 private ConcreteSubject subject;

 /// <summary>
 ///                
 /// </summary>
 public ConcreteSubject Subject
 {
  get { return subject; }
  set { subject = value; }
 }

 public ConcreteObserver(ConcreteSubject subject, string name)
 {
  this.subject = subject;
  this.name = name;
 }

 /// <summary>
 ///              
 /// </summary>
 public override void Update()
 {
  observerState = subject.SubjectState;
  Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
 }
 }
4.3 클 라 이언 트 코드

 class Program
 {
 static void Main(string[] args)
 {
  //                 
  ConcreteSubject subject = new ConcreteSubject();

  subject.Attach(new ConcreteObserver(subject, "Observer A"));
  subject.Attach(new ConcreteObserver(subject, "Observer B"));
  subject.Attach(new ConcreteObserver(subject, "Observer C"));

  subject.SubjectState = "Ready";
  subject.Notify();

  Console.Read();
 }
 }
실행 결과
//img.jbzj.com/file_images/article/201606/201606010917422.png
5.모델 총화
5.1 장점
5.1.1 관찰자 모델 은 주제 와 구체 적 인 관찰자 의 결합 을 해제 하고 결합 하 는 쌍방 이 구체 적 인 것 에 의존 하 는 것 이 아니 라 추상 에 의존 하도록 한다.그래서 각자 의 변 화 는 다른 쪽 의 변화 에 영향 을 주지 않 는 다.
5.2 단점
5.2.1 의존 관 계 는 완전히 해제 되 지 않 았 고 추상 적 인 통지 자 는 추상 적 인 관찰자 에 게 의존 했다.
5.3 필드 적용
5.3.1 한 대상 의 변화 가 다른 대상 에 게 주어 야 할 때 구체 적 으로 몇 개의 대상 이 바 뀌 어야 할 지 모른다.
5.3.2 하나의 추상 적 인 특정한 유형 은 두 가지 측면 이 있 는데 그 중의 한 가지 측면 이 다른 측면 에 의존 할 때 관찰자 모델 로 이 두 가 지 를 독립 된 대상 에 포장 하여 각자 독립 적 으로 변화 시 키 고 재 활용 할 수 있다.
 
6.모드 설명,C\#의 이벤트 의뢰 를 사용 하여 알림 자 와 관찰자 간 의 결합 을 철저히 해제 합 니 다.
6.1 의뢰 에 대한 정의:의뢰 는 인용 방법의 유형 이다.일단 위탁 을 위해 방법 을 분배 하면 위탁 은 이 방법 과 같은 행 위 를 할 것 이다.위탁 방법 은 다른 어떤 방법 과 마찬가지 로 매개 변수 와 반환 값 을 가 질 수 있다.의뢰 는 함수(방법)에 대한 추상 적 이 고 함수 의'클래스'로 볼 수 있 으 며 의뢰 의 인 스 턴 스 는 하나의(또는 여러 개)구체 적 인 함 수 를 대표 하 며 다 중 방송 할 수 있 습 니 다.
6.2 사건:사건 은 의뢰 를 바탕 으로 의뢰 에 발표/구독 체 제 를 제공 합 니 다.이벤트 의 구독 과 취 소 는 우리 가 방금 말 한 관찰자 모드 의 구독 과 취소 와 유사 하지만 표현 형식 만 다르다.관찰자 모드 에서 구독 사용 방법 Attach()로 진행 합 니 다.이벤트 구독 에'+='을 사용 합 니 다.이와 유사 하 게 구독 취 소 는 관찰자 모드 에서 Dettach()를 사용 하고 이벤트 취 소 는'-='을 사용한다.
 
7.다음 의 예 는 관찰자 모델,사건 체제 로 이 루어 진다.
7.1 사례 설명:고객 이 주문 금액 을 지불 했다.이때 재 무 는 영수증 을 발급 해 야 하고 출납 은 기장 해 야 하 며 배 송 원 은 배 송 해 야 한다.
7.2 관찰자 모델 의 실현
7.2.1 도표
//img.jbzj.com/file_images/article/201606/201606010917423.png
7.2.2 코드 구현

 /// <summary>
 ///      
 /// </summary>
 public interface ISubject
 {
 void Notify();
 }

 /// <summary>
 ///     ,           
 /// </summary>
 public abstract class JobStation
 {
 public abstract void Update();
 }

 /// <summary>
 ///     ,     
 /// </summary>
 public class Customer : ISubject
 {
 private string customerState;

 private IList<JobStation> observers = new List<JobStation>();

 /// <summary>
 ///      
 /// </summary>
 /// <param name="observer"></param>
 public void Attach(JobStation observer)
 {
  this.observers.Add(observer);
 }

 /// <summary>
 ///      
 /// </summary>
 /// <param name="observer"></param>
 public void Detach(JobStation observer)
 {
  this.observers.Remove(observer);
 }

 /// <summary>
 ///     
 /// </summary>
 public string CustomerState
 {
  get { return customerState; }
  set { customerState = value; }
 }

 public void Notify()
 {
  foreach (JobStation o in observers)
  {
  o.Update();
  }
 }
 }

 /// <summary>
 ///   
 /// </summary>
 public class Accountant : JobStation
 {
 private string accountantState;
 private Customer customer;

 public Accountant(Customer customer)
 {
  this.customer = customer;
 }

 /// <summary>
 ///     
 /// </summary>
 public override void Update()
 {
  if (customer.CustomerState == "   ")
  {
  Console.WriteLine("    ,      。");
  accountantState = "    ";
  }
 }
 }

 /// <summary>
 ///   
 /// </summary>
 public class Cashier : JobStation
 {
 private string cashierState;
 private Customer customer;

 public Cashier(Customer customer)
 {
  this.customer = customer;
 }

 public override void Update()
 {
  if (customer.CustomerState == "   ")
  {
  Console.WriteLine("     ,      。");
  cashierState = "   ";
  }
 }
 }

 /// <summary>
 ///    
 /// </summary>
 public class Dilliveryman : JobStation
 {
 private string dillivierymanState;
 private Customer customer;

 public Dilliveryman(Customer customer)
 {
  this.customer = customer;
 }

 public override void Update()
 {
  if (customer.CustomerState == "   ")
  {
  Console.WriteLine("     ,    。");
  dillivierymanState = "   ";
  }
 }
 }

7.2.3 클 라 이언 트 코드

 class Program
 {
 static void Main(string[] args)
 {

  Customer subject = new Customer();

  subject.Attach(new Accountant(subject));
  subject.Attach(new Cashier(subject));
  subject.Attach(new Dilliveryman(subject));

  subject.CustomerState = "   ";
  subject.Notify();

  Console.Read();
 }
 }
실행 결과:
저 는 회계 입 니 다.영수증 을 발급 하 겠 습 니 다.
저 는 출납원 입 니 다.등록 해 드 리 겠 습 니 다.
배 송 원 입 니 다.배 송 하 러 왔 습 니 다.
 
7.3 사건 실현
7.3.1 도표
//img.jbzj.com/file_images/article/201606/201606010917424.png
아 날로 그 를 통 해 볼 때 관찰자 와 주제 사이 에는 이미 어떠한 의존 관계 도 존재 하지 않 는 다.
7.3.2 코드 구현

 /// <summary>
 ///     
 /// </summary>
 public interface ISubject
 {
 void Notify();
 }

 /// <summary>
 ///     
 /// </summary>
 public delegate void CustomerEventHandler();

 /// <summary>
 ///     
 /// </summary>
 public class Customer : ISubject
 {
 private string customerState;

 //         ,    CustomerEventHandler
 public event CustomerEventHandler Update;

 public void Notify()
 {
  if (Update != null)
  {
  //            
  Update();
  }
 }

 public string CustomerState
 {
  get { return customerState; }
  set { customerState = value; }
 }
 }

 /// <summary>
 ///   ,              ,           
 /// </summary>
 public class Accountant
 {
 private string accountantState;

 public Accountant()
 { }

 /// <summary>
 ///    
 /// </summary>
 public void GiveInvoice()
 {
  Console.WriteLine("    ,      。");
  accountantState = "    ";
 }
 }

 /// <summary>
 ///   ,              ,           
 /// </summary>
 public class Cashier
 {
 private string cashierState;

 public void Recoded()
 {
  Console.WriteLine("     ,      。");
  cashierState = "   ";
 }
 }

 /// <summary>
 ///    ,              ,           
 /// </summary>
 public class Dilliveryman
 {
 private string dillivierymanState;

 public void Dilliver()
 {
  Console.WriteLine("     ,    。");
  dillivierymanState = "   ";
 }
 }

7.3.3 클 라 이언 트 코드

 class Program
 {
 static void Main(string[] args)
 {

  Customer subject = new Customer();

  Accountant accountant = new Accountant();
  Cashier cashier = new Cashier();
  Dilliveryman dilliveryman = new Dilliveryman();

  //     
  subject.Update += accountant.GiveInvoice;
  subject.Update += cashier.Recoded;
  subject.Update += dilliveryman.Dilliver;

  /*
  *                
  subject.Update += new CustomerEventHandler(accountant.GiveInvoice);
  subject.Update += new CustomerEventHandler(cashier.Recoded);
  subject.Update += new CustomerEventHandler(dilliveryman.Dilliver);
  */

  subject.CustomerState = "   ";
  subject.Notify();

  Console.Read();
 }
 }

실행 결과
저 는 회계 입 니 다.영수증 을 발급 하 겠 습 니 다.
저 는 출납원 입 니 다.등록 해 드 리 겠 습 니 다.
배 송 원 입 니 다.배 송 하 러 왔 습 니 다.

좋은 웹페이지 즐겨찾기