// 结账基类
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; }
}