// 結帳基類 public abstract class CashSuper { public abstract double acceptCash(double money); } // 正常模式 public class CashNomal : CashSuper { public override double acceptCash(double money) { return money; } } // 打 8 折 public class CashRebate : CashSuper { private double moneyRebate = 1d; public CashRebate(string rebate) { moneyRebate = double.Parse(rebate); } public override double acceptCash(double money) { return money * moneyRebate; } } // 滿減 public class CashReturn : CashSuper { private double moneyCondition = 0.0d; private double moneyReturn = 0.0d; public CashReturn(string condition, string re) { moneyCondition = double.Parse(condition); moneyReturn = double.Parse(re); } public override double acceptCash(double money) { if (money < moneyCondition) return money; return money - Math.Floor(money / moneyCondition) * moneyReturn; } } // 調用不一樣算法的"接口"類 public class CashContext { public CashSuper cs = null; public CashContext(string type) { switch (type) { case "正常": cs = new CashNomal(); break; case "8 折": cs = new CashRebate("0.8"); break; case "滿 200 - 50": cs = new CashReturn("200", "50"); break; default: break; } } public double GetResult(double money) { if (cs == null) return 0; return cs.acceptCash(money); } } // 業務經過"調用"類實現不一樣的算法,但內部算法具體如何實現的,外部業務不須要知道 CashContext CashContextObj = new CashContext(SelectedCostType.Name); TotalPrice = CashContextObj.GetResult(double.Parse(CurPrice) * double.Parse(CurMul));
相似與簡單工程,一樣存在後續業務新增策略時,須要修改 CashContext 類的 CashContext(string type) 的問題,違法對修改封閉的原則;算法
<Window.Resources> <localCommon:BindingProxy x:Key="Proxy" Data="{Binding}" /> </Window.Resources> <Grid Margin="20"> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <StackPanel> <StackPanel.Resources> <Style TargetType="TextBox"> <Setter Property="Width" Value="120"/> </Style> <Style TargetType="StackPanel"> <Setter Property="Margin" Value="10"/> </Style> <Style TargetType="Button"> <Setter Property="Margin" Value="10 0"/> <Setter Property="Width" Value="55"/> <Setter Property="Height" Value="25"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="Background" Value="LightSalmon"/> </Style> </StackPanel.Resources> <StackPanel Orientation="Horizontal"> <TextBlock Text="單價:"/> <TextBox Text="{Binding CurPrice, UpdateSourceTrigger=PropertyChanged}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="數量:"/> <TextBox Text="{Binding CurMul, UpdateSourceTrigger=PropertyChanged}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="折扣:" /> <ComboBox ItemsSource="{Binding CostTypeList}" Width="100" Background="Transparent" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCostType}"> </ComboBox> </StackPanel> <StackPanel Orientation="Horizontal"> <Button Content="肯定" Uid="Sure"/> <Button Content="重置" Uid="Reset"/> </StackPanel> </StackPanel> <Border Grid.Row="1" BorderBrush="LightGray" BorderThickness="1" Margin="10"> <ListBox ItemsSource="{Binding VList}" x:Name="lb"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <StackPanel.Resources> <localCommon:BindingProxy x:Key="ProxyItem" Data="{Binding}" /> </StackPanel.Resources> <StackPanel.ContextMenu> <ContextMenu> <MenuItem Header="del" Command="{Binding Source={StaticResource Proxy}, Path=Data.DelCommand}" CommandParameter="{Binding Source={StaticResource ProxyItem}, Path=Data}" /> </ContextMenu> </StackPanel.ContextMenu> <TextBlock Text="{Binding Price}" Width="350"/> <TextBlock Text="x"/> <TextBlock Text="{Binding Mul}"/> <TextBlock Text=" 折扣:" Margin="15 0 0 0"/> <TextBlock Text="{Binding Rebate}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Border> <StackPanel Grid.Row="2"> <StackPanel Orientation="Horizontal"> <TextBlock Text="總價:" /> <TextBlock Text="{Binding TureTotalPrice}" FontSize="19" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="折扣後的總價:" /> <TextBlock Text="{Binding TotalPrice}" FontSize="19" /> </StackPanel> </StackPanel> </Grid> xmal.cs public partial class Window7 : Window { public Window7() { InitializeComponent(); this.DataContext = new Window7ViewModel() {}; AddHandler(Button.ClickEvent, new RoutedEventHandler((this.DataContext as Window7ViewModel).Element_Click)); } } public class BindingProxy : Freezable { protected override Freezable CreateInstanceCore() { return new BindingProxy(); } public object Data { get { return (object)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); } public class DelegateCommand : ICommand { public Action<object> ExecuteCommand = null; public Func<object, bool> CanExecuteCommand = null; public event EventHandler CanExecuteChanged; public DelegateCommand() { } public DelegateCommand(Action<object> act) { ExecuteCommand = act; } public bool CanExecute(object parameter) { if (CanExecuteCommand != null) { return CanExecuteCommand(parameter); } else { return true; } } public void Execute(object parameter) { if (ExecuteCommand != null) this.ExecuteCommand(parameter); } public void RaiseCanExecuteChanged() { if (CanExecuteChanged != null) { CanExecuteChanged(this, EventArgs.Empty); } } } public class NotifyPropertyChanged : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// 屬性更改通知 /// </summary> /// <param name="propertyname">屬性名稱</param> public void OnProperty(string propertyname) { PropertyChangedEventHandler propertychanged = PropertyChanged; if (propertychanged != null) { propertychanged(this, new PropertyChangedEventArgs(propertyname)); } } /// <summary> /// 屬性更改通知 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="func">返回屬性的lambda表達式</param> public void RaisePropertyChange<T>(Expression<Func<T>> func) { var body = func.Body as MemberExpression; if (body != null) { var propertyinfo = body.Member; if (propertyinfo != null) { PropertyChangedEventHandler propertychanged = PropertyChanged; if (propertychanged != null) { propertychanged(this, new PropertyChangedEventArgs(propertyinfo.Name)); } } } } } public class Window7ViewModel : NotifyPropertyChanged { private string _CurPrice; public string CurPrice { get { return _CurPrice; } set { _CurPrice = value; RaisePropertyChange(() => CurPrice); } } private string _CurMul; public string CurMul { get { return _CurMul; } set { _CurMul = value; RaisePropertyChange(() => CurMul); } } private double _TureTotalPrice = 0.0d; /// <summary> /// 折扣後的總價格 /// </summary> public double TureTotalPrice { get { return _TureTotalPrice; } set { _TureTotalPrice = value; RaisePropertyChange(() => TureTotalPrice); } } private double _TotalPrice = 0.0d; /// <summary> /// 總價格 /// </summary> public double TotalPrice { get { return _TotalPrice; } set { _TotalPrice = value; RaisePropertyChange(() => TotalPrice); } } public ObservableCollection<VItem> _VList; /// <summary> /// 全部清單 /// </summary> public ObservableCollection<VItem> VList { get { if (_VList == null) { _VList = new ObservableCollection<VItem>(); } return _VList; } set { _VList = value; RaisePropertyChange(() => VList); } } public ObservableCollection<CostType> _CostTypeList; /// <summary> /// 全部折扣類型 /// </summary> public ObservableCollection<CostType> CostTypeList { get { if (_CostTypeList == null) { _CostTypeList = new ObservableCollection<CostType>(); } return _CostTypeList; } set { _CostTypeList = value; RaisePropertyChange(() => CostTypeList); } } public CostType SelectedCostType { get; set; } public DelegateCommand DelCommand { get; set; } public Window7ViewModel() { DelCommand = new DelegateCommand(new Action<object>(DelItem)); CostTypeList.Add(new CostType() { Name = "正常"}); CostTypeList.Add(new CostType() { Name = "8 折"}); CostTypeList.Add(new CostType() { Name = "滿 200 - 50"}); } private void DelItem(object obj) { try { VItem item = obj as VItem; VList.Remove(item); CashContext CashContextObj = new CashContext(item.Rebate); TotalPrice -= CashContextObj.GetResult(double.Parse(item.Price) * double.Parse(item.Mul)); TureTotalPrice -= double.Parse(item.Price) * double.Parse(item.Mul); } catch (Exception ex) { } } public void Element_Click(object sender, RoutedEventArgs e) { try { UIElement element = (UIElement)e.Source; if (element == null) element = (UIElement)e.OriginalSource; if (element == null) return; switch (element.Uid) { case "Sure": if (SelectedCostType == null) { MessageBox.Show("請選擇折扣"); return; } CashContext CashContextObj = new CashContext(SelectedCostType.Name); TotalPrice += CashContextObj.GetResult(double.Parse(CurPrice) * double.Parse(CurMul)); TureTotalPrice += double.Parse(CurPrice) * double.Parse(CurMul); VList.Add(new VItem() { Price = CurPrice, Mul = CurMul,Rebate = SelectedCostType.Name }); ResetCur(); break; case "Reset": VList.Clear(); ResetCur(); TotalPrice = 0; TureTotalPrice = 0; break; default: break; } } catch (Exception ex) { MessageBox.Show("出錯了:" + ex); } } private void ResetCur() { CurPrice = string.Empty; CurMul = string.Empty; } } /// <summary> /// 新增的每一項 /// </summary> public class VItem : NotifyPropertyChanged { private string _Price; public string Price { get { return _Price; } set { _Price = value; RaisePropertyChange(() => Price); } } private string _Mul; public string Mul { get { return _Mul; } set { _Mul = value; RaisePropertyChange(() => Mul); } } private string _Rebate; public string Rebate { get { return _Rebate; } set { _Rebate = value; RaisePropertyChange(() => Rebate); } } } /// <summary> /// 折扣類型 /// </summary> public class CostType { public string Name { get; set; } public double Cost { get; set; } }