디자인 모델 의 행위 유형 01

11278 단어
디자인 모델 의 행동 형 모델 (1)
우 리 는 창설 형 모델, 구조 형 모델 을 거 쳐 디자인 모델 의 종착역 인 행위 형 모델 에 도착 했다.
다음 에 우리 가 말 하 는 일부 모델 은 주로 대상 이나 유형 간 의 행위 와 직책 에 관심 을 가지 고 혼 란 스 러 운 코드 논리 가 유지 비용 을 증가 하지 않도록 하 는 것 이다.
책임 체인 모드
책임 체인 은 근본적으로 링크 구조 이다. 우 리 는 체인 의 맨 끝 에서 책임 져 야 할 노드 를 찾 아야 한다. 만약 에 현재 노드 가 사물 을 처리 하면 우 리 는 더 이상 찾 지 않 을 것 이다.
예 를 들 어 하나의 지주 게임 에서 우 리 는 게이머 들 이 선택 한 몇 장의 카드 가 규칙 에 부합 되 는 지 판단 해 야 한다. 우 리 는 카드 규칙 책임 체인 을 만들어 하나의 규칙 으로 판단 해 야 한다.
public class Card
{
    public int Number { get; set; }
}

public enum CardSuit
{
    Spade, Heart, Club, Diamond
}

public abstract class CardRuleDetectionBase
{
    public abstracct bool Handle(Card[] cards);
    public CardRuleDetectionBase Next { get; set; }
}

지금 우 리 는 카드 의 규칙 책임 체인 을 만 듭 니 다.
public class SingleCardRule : CardRuleDetection
{
    public override bool Handle(Card[] cards)
    {
        if(cards.Length == 1)
            return true;
        return false;
    }
}

public class DoubleCardRule : CardRuleDetection
{
    public override bool Handle(Card[] cards)
    {
        if(cards.Length == 2 && cards[0].Number == cards[1].Number)
            return true;
        return false;
    }
}

public class TripleCardRule : CardRuleDetection
{
    public override bool Handle(Card[] cards)
    {
        if(cards.Length == e && cards[0].Number == cards[1].Number && cards[1].Number == cards[2].Number)
            return true;
        return false;
    }
}

마지막 으로 이렇게 썼어 요.
public class Program
{
    public static void Main(string[] args)
    {
        var sr = new SingleCardRule();
        sr.Next = new DoubleCardRule();
        sr.Next.Next = new TripleCardRule();
        
        var cards = new []
        {
            new Card() { Number = 2 },
            new Card() { Number = 2 },
            new Card() { Number = 2 }
        };
        
        Console.WriteLine(IsCardValid(cards, sr)); // true
        
        cards = new []
        {
            new Card() { Number = 13 }
        };
        
        Console.WriteLine(IsCardValid(cards, sr)); // true
        
        cards = new []
        {
            new Card() { Number = 3 },
            new Card() { Number = 4 },
            new Card() { Number = 5 },
            new Card() { Number = 6 },
            new Card() { Number = 7 }
        };
        
        Console.WriteLine(IsCardValid(cards, sr)); // false
    }
    
    public static void IsCardValid(Card[] cards, CardRuleDetection rule)
    {
        do
        {
            if(rule.Handle(cards))
                return true;
            rule = rule.Next;
        }
        while(rule != null);
        
        return false;
    }
}

이런 체인 모드 는 제 가 별로 좋아 하지 않 아 요. 배열 해도 되 잖 아 요.
public class Program
{
    public static void Main(string[] args)
    {
        var rules = new CardRuleDetection[]
        {
            new SingleCardRule(),
            new DoubleCardRule(),
            new TripleCardRule()
        };
        
        var cards = new []
        {
            new Card() { Number = 2 },
            new Card() { Number = 2 },
            new Card() { Number = 2 }
        };
        
        Console.WriteLine(IsCardValid(rules, cards)); // true
    }
    
    public static void IsCardValid(CardRuleDetection[] rules, Card[] cards)
    {
        foreach(var r in rules)
        {
            if(r.Handle(cards))
                return true;
        }
        return false;
    }
}

명령 모드
명령 모델 은 우리 가 복잡 하고 변화 가 많은 요구 에 대응 하 는 상황 을 해결 할 수 있다. 예 를 들 어 한 회사 의 행정 부가 처리 해 야 할 것 은 매우 복잡 하 다. 만약 에 행정 부서 가 한 사람 만 있 고 그 가 하 는 일이 확실 하지 않 으 면 휴가 청구 절차 등 절차 가 변화 한 후에 그 사람 을 골 치 아 프 게 할 것 이다.
이상 적 인 상태 에서 우 리 는 이렇게 해 야 한다. 모든 일 은 숙련 된 사람 이 해 야 한다. 만약 에 이 일의 절차 가 변화 한다 면 이 사람 을 떼 어 놓 고 새로운 절 차 를 잘 아 는 사람 을 불 러 서 해 야 한다. 그리고 행정 부 서 는 주문 형식 으로 업 무 를 처리 하고 모든 사물 은 하나의 요구 내용 을 포함한다. 그러면 모든 일 을 효율적으로 처리 할 수 있다.
그러나 이런 이념 은 현실 에서 실현 불가능 할 것 이다. 그러나 절차 세계 에서 충분히 실현 할 수 있다.
우선 우 리 는 주문 처리 절 차 를 정의 합 니 다.
public interface IOrderCommand where T : Order
{
    string OrderName { get; }
    void Handle(T request);
}

public class Order
{
    public Order(string orderName)
    {
        OrderName = orderName;
    }
    public string OrderName { get; private set; }
}

public class OrderDispatch
{
    private List commands = new List();
    
    public void RegisterCommand(IOrderCommand h)
    {
        commands.Add(h);
    }
    
    public void Handle(Order order)
    {
        foreach(var c in commands)
        {
            if(o.OrderName == c.OrderName)
            {
                c.Handle(o);
                break;
            }
        }
    }
}

우 리 는 평소에 우리 회사 의 행정 업 무 를 모 의 해 보 자.
//      
public class PackageOrder : Order
{
    public PackageOrder() : base("package") { }
    
    public Package Package { get; set; }
}
public class PackageNotifyCommand : IOrderCommand
{
    public PackageNotifyCommand(QQGroup group)
    {
        this.group = group;
    }
    
    private QQGroup group;
    
    public string OrderName { get { return "package"; } }
    
    public void Handle(PackageOrder order)
    {
        var qqPersion = group.FindName(order.Package.Receiver);
        if(qqPerson != null)
            qqPerson.SendText("            ~");
    }
}


//      
public class ReimbursementOrder : Order
{
    public ReimbursementOrder() : base("reimbursement") { }
    public Person Person { get; set; }
    public String Type { get; set; }
    public float Amount { get; set; }
}

public class ReimbursementCommand : IOrderCommand
{
    public ReimbursementCommand(Cashier cashier)
    {
        this.cashier = cashier;
    }
    
    private Cashier cashier;
    
    public void Handle(ReimbursementOrder order)
    {
        if(order.Type == "food")
            return;
        var money = cashier.Request(order.Amount, order.Person.Name + ": "+order.Type);
        order.Person.Give(money);
    }
}

마지막 으로 응용 장면 을 모 의 해 보 겠 습 니 다.
public void Main()
{
    var dispatch = new OrderDispatch();
    var pnc = new PackageNotifyCommand(new QQGroup("XXX   "));
    var rc = new ReimbursementCommand(new Cashier("   "));
    dispatch.RegisterCommand(pnc);
    dispatch.RegisterCommand(rc);
    
    var pOrder = new PackageOrder();
    var package = new Package() { Receiver = "  ", content = "  " };
    pOrder.Package = package;
    dispatch.Handle(pOrder);
    
    var rOrder = new ReimbursementOrder();
    rOrder.Person = new Person () { Name = "Jim" }
    rOrder.Type = "texi";
    rOrder.Amount = 20;
    
    dispatch.Handle(rOrder);
}

만약 우리 가 가장 원시 적 인 서법 으로 돌아간다 면 어떻게 되 어야 합 니까?
public class AdminDepartment
{
    public QQGroup group;
    public Cashier cashier;
    
    public void HandlePackage(Package p)
    {
        group.FindName(p.Receiver).SendText("  !");
    }
    
    public void HandleReimbursement(Person p, string type, float amount)
    {
        if(type=="food" || type == "texi")
            return;
            
        var money = cashier.Request(amount / 2, p.Name + ": "+type);
        order.Person.Give(money);
    }
}

이상 의 방법 은 OCP 와 SRP 를 심각하게 위반 한다.다음 중 처리 해 야 할 것 이 20 개가 넘 으 면 어떻게 합 니까?
요약: 언제 우 리 는 명령 방법 을 사용 합 니까?
  • 복잡 한 것들 을 처리 해 야 한다.
  • 이런 복잡 한 사물 들 은 보통 다른 유형의 사물 처리 와 관련된다.(예 를 들 어 상기 사례 중의 QQ 군 과 출납원)
  • 이런 복잡 한 사물 들 은 어느 정도 연관 성 이 있다.(모두 행정부서 의 일)
  • 이런 복잡 한 사물 의 수량 과 내용 이 불확실 하 다.

  • 명령 모드 를 사용 할 때 주의:
    command 형식 은 위 인터페이스 에 있 는 Handle () 방법 을 제외 하고 다른 개방 방법 이 있어 서 는 안 됩 니 다.
    해석 기 모드
    략, 개인 적 인 인상 은 별로 사용 해 본 적 이 없 는 것 같 습 니 다.내 가 지정 한 데이터 (문자열 일 수도 있 고 다른 사용자 정의 데이터 일 수도 있 음) 를 마지막 으로 해석 기 를 통 해 답 을 주 겠 다 는 뜻 이다.
    응용 필드:
  • 계산기: 하나의 산식 을 입력 하여 최종 답안 을 해석한다
  • 번역 소프트웨어: 한 언어의 문장 을 입력 하여 다른 언어의 뜻 을 설명 한다.
  • 사용자 정의 프로 그래 밍 언어: 사용자 정의 프로 그래 밍 언어 코드 를 입력 하여 최종 실행 결 과 를 제시 합 니 다.어떤 언어 는 python 이나 ruby 등 이 자체 명령 행 해석 기 를 가지 고 있 고 Chrome 브 라 우 저 도 자체 적 으로 자바 script 해석 기 를 가지 고 있다.

  • 교체 기 모드
    교체 기 모드 란 무엇 입 니까?교체 기 모드 란 취 합 대상 의 각 요 소 를 순서대로 방문 하 는 방법 을 제공 하 는 것 이지 내부 의 표현 을 드 러 내 는 것 이 아니다.실제 개발 과정 에서 우 리 는 서로 다른 수 요 를 대상 으로 서로 다른 방식 으로 전체 통합 대상 을 옮 겨 다 녀 야 할 수도 있 지만 우 리 는 집적 대상 의 추상 적 인 인터페이스 층 에 다양한 편리 한 조작 이 가득 하 기 를 원 하지 않 는 다.이때 우 리 는 이런 것 이 필요 하 다. 그것 은 다음 과 같은 세 가지 기능 을 가 져 야 한다.
  • 집합 대상 을 편리 하 게 할 수 있다.
  • 우 리 는 집합 대상 의 내부 구 조 를 이해 할 필요 가 없다.
  • 다양한 옮 겨 다 니 는 방식 을 제공 할 수 있다.

  • 교체 기 라 는 것 은 C \ # 자체 테이프 입 니 다. C \ # 교체 기의 정의 가 무엇 인지 봅 시다.
    public interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }
    
    public interface IEnumerator
    {
        /// Gets the current element in the collection.
        /// The current element in the collection.
        object Current
        {
            get;
        }
    
        /// Advances the enumerator to the next element of the collection.
        /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
        /// The collection was modified after the enumerator was created. 
        bool MoveNext();
    
        /// Sets the enumerator to its initial position, which is before the first element in the collection.
        /// The collection was modified after the enumerator was created. 
        void Reset();
    }
    

    원본 코드 에서 볼 수 있 듯 이 IEnumerator 는 사용자 에 게 이 대상 의 모든 구성원 을 순서대로 방문 하 는 기능 만 주 었 을 뿐 입 니 다.
    중개 모드
    중개 라 는 두 글 자 는 즉시 나 로 하여 금 먼저 부동산 중개 에 도착 하 게 했다.프로그램 개발 중의 중개 와 주택 중 개 는 비슷 한 상황 이 있다. 미래 에 세입 자 와 집주인 간 에 만 나 거나 의사 소통 이 불편 하 다 (예 를 들 어 여가 사건 이 일치 하지 않 고 언어 가 통 하지 않 는 문제) 는 중개 가 쌍방 을 대신 하여 의사 소통 을 완성 한다.
    프로그램 개발 에서 우 리 는 A 대 시스템 의 하위 기능 중 하나 가 B 대 시스템 의 하위 기능 과 서로 소통 해 야 한 다 는 문제 에 자주 부 딪 힌 다.
    그러나 A 대 기능 이 있 는 환경 과 B 대 기능 은 전혀 교 집합 되 지 않 았 다.A 는 B 를 인용 할 수 없 거나 A 는 B 를 인용 해 서 는 안 된다.이 럴 때 는 중개 모드 가 필요 하 다.
    예 를 들 어 아이스크림 공장 안 에는 7 개의 큰 단계 가 있 는데 각 단계 이론 적 으로 서로 독립 되 고 서로 영향 을 주지 않 지만 연결 할 때 서로 처리 해 야 할 것들 이 나타 나 는 것 을 피하 기 어렵다.
    한 접시 에 담 긴 그릇 은 여러 가지 이유 로 다음 단계 에 직접 전달 되 는 것 이 아니 라 다음 단계 에 직접 그릇 을 새로 만 드 는 것 이다.이 로 인해 감상 적 으로 두 개의 그릇 이 생 긴 상황 이다.그래서 다음 단 계 는 이전 단계 에 오래된 그릇 을 숨 기 라 고 알려 야 한다.
    두 단 계 는 서로 독립 되 어 있 기 때문에 그들 은 상대방 을 쉽게 (또는 아름 답 게) 인용 할 수 없 기 때문에 우 리 는 알림 센터 라 는 종 류 를 사용 했다.
    설정: 이전 단 계 는 A 이 고 다음 단 계 는 B 이 며 알림 센터 는 C 입 니 다.A 는 C 가 앞으로 보 낼 '숨 은 그릇' 의 소식 을 감청 하고 이 소식 을 들 은 후에 그릇 을 숨긴다.B. 적당 한 이벤트 에 "그릇 숨 기기" 메 시 지 를 C 에 게 보 내기;C 는 소식 을 들 은 후에 A 가 이 소식 을 필요 로 하 는 것 을 발견 하고 C 는 A 의 처리 방법 을 호출 했다.A 는 그릇 을 숨 기 는 데 성공 했다.
    그래서 A 와 B 사이 의 통신 은 이렇게 생 겼 다.그러나 그들 사이 에는 직접적인 관계 가 없다.
    결론: 중개 모델 을 사용 하 는 상황 은 A 와 B 가 상대방 을 아름 답 게 인용 할 수 없 거나 아름 답 게 인용 할 수 없 는 경우 이다. 이때 제3자 가 끼어 들 어 A 와 B 가 서로의 의사 소통 을 완성 해 야 한다.

    좋은 웹페이지 즐겨찾기