Xamarin 개발 : 쇼핑몰 프로모션 (전략 디자인 패턴)

1. 소개

본 글은 학습 및 분석을 위해 『다화 디자인 패턴』 2장의 내용을 인용하였으며, 학습 목적으로만 작성되었습니다.

내 마지막 기사 Xamarin Development: Basics는 다음과 같습니다. 전략적 디자인 패턴을 사용하여 여기에서 계속
작성합니다. 소위 코드 디자인은 단지 특정 디자인 패턴을 참조하는 것이 아닙니다. 예를 들어, 다음에 소개할 전략적 디자인 패턴은 실제로 다음을 기반으로 합니다. 단순한 공장 설계 패턴을 변형한 것에서 파생되므로, 코드 로직을 설계할 때 코드에 얽매이지 않고 특정 설계 패턴을 사용하여 구현해야 하며, 대신 요구 사항을 세분화하고 어떤 설계가 구체적으로 분석되어야 하는지를 알아야 합니다. 우리가 생각하는 디자인 패턴은 사실 우리가 일반적으로 복잡한 코드를 표준화하고, 코드의 중복과 중복성을 줄이고, 우리 코드를 더 단순하게 만들고, 나중에 다른 프로그램에서 로직이 단순하고 코드가 명확하다는 느낌을 주도록 하는 것입니다. 본다. , 이는 프로그래머가 갖춰야 할 능력이기도 하다.

2. 수요분석

먼저 아래와 같이 요구사항을 살펴보겠습니다.
여기에 이미지 설명을 삽입하세요.

여기서는 먼저 계산방법 의 문제를 제쳐두고 단가수량만
간단히 입력하고 확인버튼을 누르면 합계가 계산 되어 TextView에 표시됩니다 단가: xx 수량: xx 총계: xx를 클릭하고 재설정 기능만 설정하세요

프로그래밍을 처음 접하는 사람들에게는 여기에서의 분석이 철저하지 않을 수 있으며 기능을 실현하기 위해 구현되었을 뿐이지만 문제가 되지 않습니다. 우리는 코드를 단계별로 최적화하고 표준화하여 다른 사람들이 생각을 볼 수 있도록 할 수 있습니다. 분명히.

3. 실현

여기에서는 클릭 시간과 라벨 속성이 어떻게 등록되고 호출되는지 설명하지 않겠습니다. 모르신다면 제 이전 글을 읽어보세요.

Vs에서 ViewController.cs 스크립트를 엽니다.

이것은 서면 논리가 없는 스크립트입니다.

namespace ShoppingMall
	{
    
    
    public partial class ViewController : NSViewController
    {
    
    
        public ViewController(IntPtr handle) : base(handle)
        {
    
    

        }

        public override void ViewDidLoad()
        {
    
    
            base.ViewDidLoad();
            // Do any additional setup after loading the view.
        }

        public override NSObject RepresentedObject
        {
    
    
            get
            {
    
    
                return base.RepresentedObject;
            }
            set
            {
    
    
                base.RepresentedObject = value;
                // Update the view, if already loaded.
            }
        }
    }

여기에 확인 이벤트를 등록 하고 버튼을 클릭하세요 .

 /// <summary>
        /// Makes the sure.确认按钮
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void MakeSure(NSButton sender)
        {
    
    
            throw new NotImplementedException();
        }

        /// <summary>
        /// Resert the specified sender.重置按钮
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void Resert(NSButton sender)
        {
    
    
            throw new NotImplementedException();
        }

작성 논리는 다음과 같습니다

	/// <summary>
        /// The m price.单价
        /// </summary>
        private double m_price = 0d;

        /// <summary>
        /// The m amount.数量
        /// </summary>
        private double m_amount = 0d;

        /// <summary>
        /// The m totalmoney.未折扣价格
        /// </summary>
        private double m_totalmoney = 0d;

        /// <summary>
        /// Makes the sure.确认按钮
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void MakeSure(NSButton sender)
        {
    
    
            if (string.IsNullOrEmpty(PriceField.StringValue) || string.IsNullOrEmpty(AmountField.StringValue))
                return;
            m_price = double.Parse(PriceField.StringValue);
            m_amount = double.Parse(AmountField.StringValue);
            m_totalmoney = m_price * m_amount;

            TotalPrice.StringValue = m_totalmoney.ToString();

            TextView.Value = "单价:" + m_price + " 数量:" + m_amount + " 正常收费 合计:" + m_totalmoney;
        }

        /// <summary>
        /// Resert the specified sender.重置按钮
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void Resert(NSButton sender)
        {
    
    
            PriceField.StringValue = string.Empty;
            AmountField.StringValue = string.Empty;
            TextView.Value = string.Empty;
            TotalPrice.StringValue = "0.00";
        }

기능은 다음과 같습니다
여기에 이미지 설명을 삽입하세요.

4. 수요분석

여기서는 위의 코드를 분석합니다:
질문 1: 코드에서 double.Parse()가 많이 사용됩니다. 어떻게 해결합니까?
질문 2: 이때 새로운 요구가 제기되고 있는데 할인을 활용해야 하는데 어떻게 하면 더 적절하게 대처할 수 있나요?

문제 1 해결 방법

여기에 도구 클래스를 작성하세요. string.ToDouble()만 있으면 됩니다.

public static class Tools
    	{
    
    
        	public static double ToDouble(this string str) 
        	{
    
    
            double dbl = 0d;
            double.TryParse(str,out dbl);
            return dbl;
        }
    }

문제 2에 대한 해결책

여기에 드롭다운 메뉴(팝업 버튼)를 추가할 수 있으며,
드롭다운 메뉴의 옵션을 초기화해야 합니다.

여기에서는 드롭다운 목록 옵션을 저장하기 위해 Const 클래스를 작성하고 있습니다.

public class Const
    {
    
    
        public static string[] PullDown = {
    
     "请选择计费方式", "正常收费", "八折" };
    }

드롭다운 목록 이벤트를 등록하고 초기화 방법을 작성합니다.

    /// <summary>
        /// Init this instance.初始化
        /// </summary>
        public void Init()
        {
    
    
            PullDown.RemoveAllItems();
            PullDown.AddItems(Const.PullDown);
        }

        /// <summary>
        /// Drops down.下拉列表选择
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void DropDown(NSPopUpButton sender)
        {
    
    
            PullDown.Title = sender.TitleOfSelectedItem;
        }
这里的Init方法放在加载窗口之后直接执行

        public override void ViewDidLoad()
        {
    
    
            base.ViewDidLoad();
            Init();
            // Do any additional setup after loading the view.
        }

여기서 할인 처리를 분석해 보겠습니다. 할인된 일반 요금을 객체로 처리한 다음 상속하기 위해 생성한 객체에 대한 추상 클래스를 작성하고 마지막으로 객체를 인스턴스화하는 간단한 팩토리를 작성하여 코드와 코드의 결합을 줄일 수 있습니다. 후속 수정은 다른 클래스에 영향을 미치지 않습니다.

클릭 이벤트의 최종 코드를 다음과 같이 수정합니다.

	/// <summary>
    /// Cash super.抽象类
    /// </summary>
	public abstract class CashSuper
    {
    
    
        public abstract double AcceptCash(double money);
    }

    /// <summary>
    /// Cash normal.正常
    /// </summary>
    public class CashNormal : CashSuper
    {
    
    
        public override double AcceptCash(double money)
        {
    
    
            return money;
        }
    }

    /// <summary>
    /// Cash rebate.打折
    /// </summary>
    public class CashRebate : CashSuper
    {
    
    
        private double moneyRebate = 1d;

        public CashRebate(string moneyRebate) 
        {
    
    
            this.moneyRebate = double.Parse(moneyRebate);
        }

        public override double AcceptCash(double money)
        {
    
    
            return money * moneyRebate;
        }
    }

간단한 공장:

	public class CashFactory
    {
    
    
        public static CashSuper CreateCashAccept(string type) 
        {
    
    
            CashSuper super = null;
            switch (type)
            {
    
    
                case "正常收费":
                    super = new CashNormal();
                    break;
                case "八折":
                    super = new CashRebate("0.8");
                    break;
                default:
                    break;
            }
            return super;
        }
    }

클릭 이벤트 수정

      /// <summary>
        /// The discount.折扣价
        /// </summary>
        private double m_discount = 0d;

        /// <summary>
        /// Makes the sure.确认按钮
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void MakeSure(NSButton sender)
        {
    
    
            if (string.IsNullOrEmpty(PriceField.StringValue) || string.IsNullOrEmpty(AmountField.StringValue))
                return;
            m_price = PriceField.StringValue.ToDouble();
            m_amount = AmountField.StringValue.ToDouble();
            m_totalmoney = m_price * m_amount;

            //简单工厂模式
            CashSuper super = CashFactory.CreateCashAccept(PullDown.Title);
            m_discount = super.AcceptCash(m_totalmoney);

            TotalPrice.StringValue = m_discount.ToString();

            TextView.Value = "单价:" + m_price + " 数量:" + m_amount + " 合计:" + m_discount;
        }

여기에 이미지 설명을 삽입하세요.

5. 새로운 수요 추가

이번에 전액할인 이벤트를 추가했는데, 300 이상 구매시 100 할인이 가능합니다.

이때 전체 빼기 클래스만 추가하고 간단한 팩토리를 수정하면 완벽하게 해결할 수 있다고 분석합니다.

새로운 카테고리:

/// <summary>
    /// Cash return.返利
    /// </summary>
    public class CashReturn : CashSuper
    {
    
    
        private double moneyCondition = 0d;

        private double moneyReturn = 0d;

        public CashReturn(string moneyCondition,string moneyReturn) 
        {
    
    
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }

        public override double AcceptCash(double money)
        {
    
    
            if (money >= moneyCondition)
                return money - Math.Floor(money / moneyCondition) * moneyReturn;
            return money;
        }
    }

간단한 팩토리 클래스 수정:

public class CashFactory
    {
    
    
        public static CashSuper CreateCashAccept(string type) 
        {
    
    
            CashSuper super = null;
            switch (type)
            {
    
    
                case "正常收费":
                    super = new CashNormal();
                    break;
                case "八折":
                    super = new CashRebate("0.8");
                    break;
                case "满300减100":
                    super = new CashReturn("300","100");
                    break;
                default:
                    break;
            }
            return super;
        }
    }

기능은 다음과 같습니다:
여기에 이미지 설명을 삽입하세요.

6. 코드 최적화 및 분석

여기에서는 확인 버튼 클릭 이벤트의 로직을 살펴보겠습니다
. 이제 결과를 얻으면 두 클래스를 호출해야 합니다. 하나는 추상 클래스이고 다른 하나는 팩토리 클래스입니다. 이는 작업에 도움이 되지 않습니다. 이때 간단한 팩토리를 전략 패턴과 결합하여 코드를 더욱 간결하게 만들어야 합니다.

다음과 같이:

public class CashContext
    {
    
    
        private CashSuper m_cashsuper = null;

        public CashContext(string type)
        {
    
    
            switch (type)
            {
    
    
                case "正常收费":
                    m_cashsuper = new CashNormal();
                    break;
                case "八折":
                    m_cashsuper = new CashRebate("0.8");
                    break;
                case "满300减100":
                    m_cashsuper = new CashReturn("300", "100");
                    break;
                default:
                    m_cashsuper = null;
                    break;
            }
        }

        public double GetResult(double money)
        {
    
    
            return m_cashsuper.AcceptCash(money);
        }
    }

클릭 이벤트 수정:

/// <summary>
        /// Makes the sure.确认按钮
        /// </summary>
        /// <param name="sender">Sender.</param>
        partial void MakeSure(NSButton sender)
        {
    
    
            if (string.IsNullOrEmpty(PriceField.StringValue) || string.IsNullOrEmpty(AmountField.StringValue))
                return;
            m_price = PriceField.StringValue.ToDouble();
            m_amount = AmountField.StringValue.ToDouble();
            m_totalmoney = m_price * m_amount;

            简单工厂模式
            //CashSuper super = CashFactory.CreateCashAccept(PullDown.Title);
            //m_discount = super.AcceptCash(m_totalmoney);

            //简单工厂与策略模式结合
            CashContext cc = new CashContext(PullDown.Title);
            m_discount = cc.GetResult(m_totalmoney);

            TotalPrice.StringValue = m_discount.ToString();

            TextView.Value = "单价:" + m_price + " 数量:" + m_amount + " 合计:" + m_discount;
        }

이렇게 하면 코드가 더 간결해집니다. 클래스에서 작업하면 됩니다.

UML 클래스 다이어그램:여기에 이미지 설명을 삽입하세요.

요약하다

실제로 전략 패턴은 실제로 일련의 알고리즘을 정의하는 방법이다. 개념적으로 모든 알고리즘은 동일한 작업을 구현하지만 구현이 다르다. 모든 알고리즘을 동일한 방식으로 호출할 수 있어 다양한 알고리즘 클래스를 줄일 수 있다. 알고리즘 클래스와의 결합.

이점: 단위 테스트가 단순화됩니다. 각 알고리즘에는 자체 클래스가 있으며 다른 클래스에 영향을 주지 않고 자체 인터페이스를 통해 별도로 테스트할 수 있습니다.

참고: 전략 모드는 다양한 알고리즘을 캡슐화하므로 많은 판단을 피할 수 없습니다. 따라서 현재로서는 if나 스위치 모두 실제로 최선의 선택이 아닙니다. 반사를 사용하도록 선택할 수 있습니다. 반사에 대해서는 추후 블로그에서 설명하겠습니다 .

추천

출처blog.csdn.net/qq_42194657/article/details/135422773