使用WPF创建计算机【简陋版】

 

简单工厂 VS 工厂方法

 区别:简单工行模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

如果要讲一个【求M数的N次方】的功能,我们是一定需要给运算工厂类的方法里加【case】的分支条件,修改原来的类,这就扥估说,我们不但对扩展开放了,对修改也开放了,这就违背了【开放-封闭原则】

工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化那个类。工厂方法是一个类的实例化延迟到其子类。使用WPF创建计算机【简陋版】_第1张图片

根据依赖倒置原则,我们我工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要声场具体类的工厂,就去实现这个剪口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生产对象的工厂,于是我们要增加【求M数的N次方】的功能时,就不需要更改原有的工厂类了,值需要增加此功能的运算类和相应的工厂类就可以了。

使用WPF创建计算机【简陋版】_第2张图片

其实你仔细观察就会发现,工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法吧简单工厂的内容逻辑判断移到了客户端代码来进行。你想要加功能,原本是改工厂类,而现在是修改客户端!

工厂方法保持了简单工厂模式的优点,而且克服了他的缺点。但缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量,

“那有没有最佳的做法呢?尅不已避免修改客户端的代码呢?”

可以利用【反射】来解决避免分支判断的问题。

                                                                                                             以上内容均来之《大话设计模式》——第八章


 

程序介绍:

使用WPF创建计算机【简陋版】_第3张图片


XAML文件内容: 


    
        
    
    
        
            
            
            
            
        
        
            
            
            
            
            
            
        
        
            
                
            
            
                
                    
                    
                
            
            
                
            
        
        
            
                

Factory文件:

抽象工厂:

    /// 
    /// 抽象工厂
    /// 
    public interface IFactoty
    {
        Operator CreateOperator(string num1);
    }

加法工厂 :

    /// 
    /// 加法工厂
    /// 
    public class AddFactoty : IFactoty
    {
        public Operator CreateOperator(string num1)
        {
            return new OperatorAdd(num1);
        }
    }

其他的减法、乘法、除法、百分比我就不一一写上去了,请自己模仿一下加法工厂。 


Operators文件

运算类:

    /// 
    /// 运算类
    /// 
    public class Operator : INotifyPropertyChanged
    {
        /// 
        /// 正则表达式
        /// 
        private string regexString = @"^(-?\d+)(\.\d+)?$";
        /// 
        /// 最大长度
        /// 
        private readonly int MaxLength = 15;
        private string num1;
        private string num2;
        private OperatorEnum sign;
        private string result;
        /// 
        /// 第一位数
        /// 
        public string Num1
        {
            get { return num1; }
            set
            {
                if (value.Length > MaxLength)
                {
                    return;
                }
                if (value == "分母不能为0")
                {
                    value = num1;
                }
                value = ChangeDataToD(value);
                bool flag = NumberValidator(value);
                if (flag)
                {
                    num1 = value; OnPropertyChanged("Num1");
                    if (Sign == OperatorEnum.None)
                    {
                        Result = Num1;
                    }
                }
                else
                {
                    throw new Exception("请输入正确的数字!");
                }
            }
        }
        /// 
        /// 第二位数
        /// 
        public string Num2
        {
            get
            {
                return num2;
            }
            set
            {
                if (value.Length > MaxLength)
                {
                    return;
                }
                value = ChangeDataToD(value);
                bool flag = NumberValidator(value);
                if (flag)
                {
                    num2 = value; OnPropertyChanged("Num2");
                }
                else
                {
                    throw new Exception("请输入正确的数字!");
                }
            }
        }
        /// 
        /// 运算符
        /// 
        public OperatorEnum Sign
        {
            get { return sign; }
            set { sign = value; OnPropertyChanged("Sign"); }
        }
        /// 
        /// 运算结果
        /// 
        public string Result
        {
            get { return result; }
            set
            {
                if (value == "分母不能为0")
                {
                    result = value;
                }
                else
                {
                    value = ChangeDataToD(value);
                    if (value.Length > MaxLength)//大于则四舍五入
                    {
                        result = Math.Round(Convert.ToDecimal(value), MaxLength, MidpointRounding.AwayFromZero).ToString();
                    }
                    else
                    {
                        result = value;
                    }
                }
                OnPropertyChanged("Result");
            }
        }
        /// 
        /// 分母是否为零
        /// 
        public bool IsError { get; set; }
        /// 
        /// 是否已求和
        /// 
        public bool IsEnter { get; set; }
        public Operator()
        {
            Num1 = "0";
            IsError = false;
            IsEnter = false;
            Sign = OperatorEnum.None;
        }
        /// 
        /// 求解
        /// 
        /// 
        public virtual void GetResult()
        {

        }
        /// 
        /// 数字累加
        /// 
        /// 
        public void InitDigital(string text)
        {
            if (Sign == OperatorEnum.None || Sign == OperatorEnum.Percentage)//第一位数累加
            {
                if ((Num1 == "0" || Num1 == null) && text != ".")
                {
                    Num1 = text;
                }
                else
                {
                    Num1 += text;
                }
            }
            else if (Sign != OperatorEnum.None && Sign != OperatorEnum.Percentage)//第二位数累加
            {
                if ((Num2 == "0" || Num1 == null) && text != ".")
                {
                    Num2 = text;
                }
                else
                {
                    Num2 += text;
                }
                GetResult();
            }
            else
            {
                Result += text;
            }
        }
        /// 
        /// 退格
        /// 
        public void BackSpace()
        {
            if (Sign == OperatorEnum.None && !IsEnter)//还未计算,后退第一位数
            {
                if (Num1.Length <= 1)
                {
                    Num1 = "0";
                }
                else
                {
                    Num1 = Num1.Substring(0, (Num1.Length - 1));
                }
                Result = Num1;
            }
            else if (Sign != OperatorEnum.None && Sign != OperatorEnum.Percentage && !IsEnter)//按了运算符,后退第二位数
            {
                if (Num2.Length <= 1)
                {
                    Num2 = "0";
                }
                else
                {
                    Num2 = Num2.Substring(0, (Num2.Length - 1));
                }
                GetResult();
            }
            else if (IsEnter)//已求和禁止退格
            {
                return;
            }
        }
        /// 
        /// 科学计数法转化为正常数值
        /// 
        /// 
        /// 
        private string ChangeDataToD(string strData)
        {
            Decimal dData = 0.0M;
            if (strData.Contains("E"))
            {
                dData = Convert.ToDecimal(Decimal.Parse(strData.ToString(), System.Globalization.NumberStyles.Float));
                return dData.ToString();
            }
            else
            {
                return strData;
            }
        }
        /// 
        /// 数字格式验证
        /// 
        /// 
        /// 
        private bool NumberValidator(string value)
        {
            string num = Convert.ToDouble(value).ToString();
            num = ChangeDataToD(num);
            Match m = Regex.Match(num, regexString);
            if (m.Success)
            {
                if (num != "0" && Sign == OperatorEnum.Division)
                {
                    IsError = false;
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

除法时,需要考虑分母是否为0 ,同时我还将科学计算法转化为普通数字,如【0.2e-700=>0.00000032】,如果不需要的话,你可以删除。

加法类:

    /// 
    /// 加法类
    /// 
    public class OperatorAdd: Operator
    {
        public OperatorAdd(string num1)
        {
            Sign = OperatorEnum.Additive;
            Num1 = num1;
        }
        public override void GetResult()
        {
            if (Num2 == "")
            {
                Num2 = "0";
            }
            Result = (Convert.ToDouble(Num1) + Convert.ToDouble(Num2)).ToString();
        }
    }

除法类: 

    /// 
    /// 除法类
    /// 
    class OperatorDiv : Operator
    {
        public OperatorDiv(string num1)
        {           
            Sign = OperatorEnum.Division;
            Num1 = num1;
        }
        public override void GetResult()
        {
            if (Num2 != null && Convert.ToDouble(Num2) != 0 && !IsError)//分母为0不能求和
            {
                Result = (Convert.ToDouble(Num1) / Convert.ToDouble(Num2)).ToString();
            }
            else
            {
                Result = "分母不能为0";
                IsError = true;
            }
        }
    }

除法需要考虑分母不能为0 ,并作出相关提示!

使用WPF创建计算机【简陋版】_第4张图片

百分比类:

    /// 
    /// 百分比类
    /// 
    public class OperatorPer:Operator
    {
        public OperatorPer(string num1)
        {
            Sign = OperatorEnum.Percentage;
            Num1 = num1;
        }
        public override void GetResult()
        {
            Result = (Convert.ToDouble(Num1) / 100).ToString();
        }
    }

百分比仅对第一位数处理。 

减法类、乘法类就不在写上了,请自己模仿一下加法类。


运算符枚举:

    /// 
    /// 运算符枚举
    /// 
    public enum OperatorEnum
    {
        /// 
        /// 加法
        /// 
        Additive = 1,
        /// 
        /// 减法
        /// 
        Subduction = 2,
        /// 
        /// 乘法
        /// 
        Multiplication = 3,
        /// 
        /// 除法
        /// 
        Division = 4,
        /// 
        /// 百分比
        /// 
        Percentage = 5,
        /// 
        /// 没有
        /// 
        None = 0
    }

目前计算器支持:加法、减法、乘法、除法和百分比。需要添加额外方法,请模仿工厂和运算类。


枚举转化 : 

     /// 
    /// 运算符枚举转字符串
    /// 
    public class OperatorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
                return "";
            OperatorEnum operatorEnum = StrToOperatorEnum(value.ToString());
            switch (operatorEnum)
            {
                case OperatorEnum.Additive:
                    return "+";
                case OperatorEnum.Subduction:
                    return "-";
                case OperatorEnum.Multiplication:
                    return "*";
                case OperatorEnum.Division:
                    return "/";
                case OperatorEnum.Percentage:
                    return "%";
                case OperatorEnum.None:                   
                default:
                    return "";
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
        /// 
        /// 字符串转运算符枚举
        /// 
        /// 
        /// 
        private OperatorEnum StrToOperatorEnum(string text)
        {
            if (text == "Additive")
            {
                return OperatorEnum.Additive;
            }
            else if (text == "Subduction")
            {
                return OperatorEnum.Subduction;
            }
            else if (text == "Multiplication")
            {
                return OperatorEnum.Multiplication;
            }
            else if (text == "Division")
            {
                return OperatorEnum.Division;
            }
            else if (text == "Percentage")
            {
                return OperatorEnum.Percentage;
            }
            else
            {
                return OperatorEnum.None;
            }
        }
    }

需要实现IValueConverter 接口,使用于WPF界面。具体接口介绍,请百度搜索相关内容。


MainWindow.xaml 的交互逻辑:

    /// 
    /// MainWindow.xaml 的交互逻辑
    /// 
    public partial class MainWindow : Window
    {
        private static Operator calcCategory = new Operator ();
        private static readonly double FontSize = 38;
        IFactoty factoty = null;
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = calcCategory;
        }
        /// 
        /// 点击数字
        /// 
        /// 
        /// 
        private void btn_Click(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            string text = btn.Content.ToString();
            calcCategory.InitDigital(text);
        }        
        /// 
        /// 点击操作符
        /// 
        /// 
        /// 
        private void btn_Operator(object sender, RoutedEventArgs e)
        {
            ControlOperator();
            var btn = sender as Button;
            string text = btn.Content.ToString();
            GetOperator(text);
        }
        /// 
        /// 获取运算符
        /// 
        /// 
        private void GetOperator(string text)
        {
            if (this.ShowNumResult.Text=="分母不能为0")
            {
                return;
            }
            calcCategory.IsEnter = false;            
            OperatorEnum operatorEnum = StrToOperatorEnum(text);
            switch (operatorEnum)
            {                
                case OperatorEnum.Subduction:
                    factoty = new SubFactoty();                    
                    break;
                case OperatorEnum.Multiplication:
                    factoty = new MulFactoty();
                    break;
                case OperatorEnum.Division:
                    factoty = new DivFactoty();
                    break;
                case OperatorEnum.Percentage:
                    factoty = new PerFactoty();
                    calcCategory = factoty.CreateOperator(this.ShowNum1Text.Text);
                    calcCategory.GetResult();
                    this.DataContext = calcCategory;
                    return;
                case OperatorEnum.Additive:                 
                case OperatorEnum.None:
                default:
                    factoty = new AddFactoty();
                    break;
            }
            calcCategory = factoty.CreateOperator(this.ShowNum1Text.Text);
            calcCategory.GetResult();
            calcCategory.Result = calcCategory.Num1;
            this.DataContext = calcCategory;
        }
        /// 
        /// 求和
        /// 
        /// 
        /// 
        private void btn_ToEqual(object sender, RoutedEventArgs e)
        {
            if (calcCategory.IsError && calcCategory.Sign == OperatorEnum.Division)
            {
                return;
            }
            calcCategory.GetResult();
            calcCategory.IsEnter = true;
            this.ShowNum1Text.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBFBFBF"));
            this.ShowNum2Text.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBFBFBF"));
            this.ShowOperText.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBFBFBF"));
            this.ShowNumResult.Foreground = new SolidColorBrush(Colors.Black);
        }
        /// 
        /// 全清
        /// 
        /// 
        /// 
        private void btn_Clear_Click(object sender, RoutedEventArgs e)
        {
            calcCategory = new Operator();
            this.DataContext = calcCategory;
            this.ShowNum1Text.FontSize = FontSize ;
            this.ShowNumResult.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBFBFBF"));
        }
        /// 
        /// 退格
        /// 
        /// 
        /// 
        private void btn_BackSpace(object sender, RoutedEventArgs e)
        {
            calcCategory.BackSpace();
        }
        /// 
        /// 键盘事件
        /// 
        /// 
        /// 
        private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            int KeyValue = (int)e.Key;
            int num = 0;
            if (KeyValue > 73 && KeyValue < 84)
            {
                num = KeyValue - 74;
                calcCategory.InitDigital(num.ToString());
            }
            else if (KeyValue > 33 && KeyValue < 44)
            {
                num = KeyValue - 34;
                calcCategory.InitDigital(num.ToString());
            }
            else if(e.Key == Key.Decimal)
            {
                calcCategory.InitDigital(".");
            }
            else if (e.Key == Key.Add)
            {
                ControlOperator();
                GetOperator("+");
            }
            else if (e.Key == Key.Subtract)
            {
                ControlOperator();
                GetOperator("-");
            }
            else if (e.Key == Key.Multiply)
            {
                ControlOperator();
                GetOperator("*");
            }
            else if (e.Key == Key.Divide)
            {
                ControlOperator();
                GetOperator("/");
            }
            else if ((Keyboard.IsKeyDown(Key.LeftShift) && Keyboard.IsKeyDown(Key.D5)) || (Keyboard.IsKeyDown(Key.RightShift) && Keyboard.IsKeyDown(Key.D5)))
            {
                ControlOperator();
                GetOperator("%");
            }
            else if (e.Key == Key.Back)
            {
                calcCategory.BackSpace();
            }
            else if (e.Key == Key.Escape)
            {
                btn_Clear_Click(sender, e);
            }
            else if (e.Key == Key.Enter)
            {
                btn_ToEqual(sender, e);
            }
        }
        /// 
        /// 点击操作符,控件样式变化
        /// 
        private void ControlOperator()
        {
            if (calcCategory.Result != "")
            {
                calcCategory.Num1 = calcCategory.Result;
                this.ShowNum1Text.FontSize = FontSize * 0.75;
                this.ShowNum1Text.Foreground = new SolidColorBrush(Colors.Black);
                this.ShowNum2Text.Foreground = new SolidColorBrush(Colors.Black);
                this.ShowOperText.Foreground = new SolidColorBrush(Colors.Black);
                this.ShowNumResult.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFBFBFBF"));
            }
        }
        /// 
        /// 字符串转运算符枚举
        /// 
        /// 
        /// 
        private OperatorEnum StrToOperatorEnum(string text)
        {
            if (text == "+")
            {
                return OperatorEnum.Additive;
            }
            else if (text == "-")
            {
                return OperatorEnum.Subduction;
            }
            else if (text == "*")
            {
                return OperatorEnum.Multiplication;
            }
            else if (text == "/")
            {
                return OperatorEnum.Division;
            }
            else if (text == "%")
            {
                return OperatorEnum.Percentage;
            }
            else
            {
                return OperatorEnum.None;
            }
        }
        /// 
        /// 运算符枚举转字符串
        /// 
        /// 
        /// 
        private string OperatorEnumToStr(OperatorEnum  operatorEnum)
        {
            switch (operatorEnum)
            {
                case OperatorEnum.Additive:
                    return "+";
                case OperatorEnum.Subduction:
                    return "+";
                case OperatorEnum.Multiplication:
                    return "+";
                case OperatorEnum.Division:
                    return "+";
                case OperatorEnum.Percentage: 
                    return "%";
                case OperatorEnum.None:                    
                default:
                    return "";
            }
        }
    }
        /// 
        /// 计算字体大小
        /// 
        private void CalculateFontSize(TextBlock ShowNumText)
        {
            try
            {
                var formattedText = new FormattedText(
    ShowNumText.Text,
    System.Globalization.CultureInfo.CurrentUICulture,
    FlowDirection.LeftToRight,
    new Typeface(ShowNumText.FontFamily, ShowNumText.FontStyle, ShowNumText.FontWeight, ShowNumText.FontStretch),
    ShowNumText.FontSize,
    Brushes.Black);
                Size size = new Size(formattedText.Width, formattedText.Height);
                double maxTextWidth = 420;
                string a = size.ToString().Split(',')[0];
                double newTextWidth = double.Parse(a);
                double borderHeight = this.NumBorder.ActualHeight;
                double TextHeight = ShowNumText.ActualHeight;
                if (maxTextWidth < newTextWidth)
                {
                    ShowNumText.FontSize -= 5;

                    CalculateFontSize(ShowNumText);
                }
                else if (((maxTextWidth / 1.5) > newTextWidth) && (borderHeight / 1.2) > size.Height)
                {
                    ShowNumText.FontSize += 5;
                    CalculateFontSize(ShowNumText);
                }
                else
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }            
        }

 效果图:

整个程序是模仿小米6的计算器!

使用WPF创建计算机【简陋版】_第5张图片使用WPF创建计算机【简陋版】_第6张图片使用WPF创建计算机【简陋版】_第7张图片使用WPF创建计算机【简陋版】_第8张图片


虽然里面还有些小瑕疵,可读性不强,类名也是乱取的,但还是马马虎虎的做出来了。。。

你可能感兴趣的:(#,WPF,C#)