策略模式实现搜索功能

概念:

策略模式是一种行为设计模式,用于定义一系列算法,将他们封装起来,并使他们可以互相替换。使用策略模式可以让代码更加灵活,且易于扩展和维护

背景:

假设你有一个功能需要多种不同的算法或行为实现(如不同的排序方式、不同的支付方式、不同的搜索方式等),这些行为是相似的。但是在细节上有所不同。

核心:

将这些可变的行为封装为不同的策略累,并定义一个接口来规范这些策略的实现。这样就可以在运行时动态切换策略,而不需要修改客户端的代码

用途:

1、替换不同的算法:可以根据需要动态的选择不同的算法或实现。比如不同的折扣策略,不同的支付方式

2、简化条件语句:用策略模式可以替换大量的if-else语句

3、提高可扩展性:新增一种行为时,只需要添加一个新的策略类,而不需要修改现有的代码

基本结构:

1、策略接口(Strategy Interface):定义所有策略类必须实现的方法。

2、具体策略类(Concrete Strategy):每个类实现具体的算法或行为。

3、上下文类(Context):持有一个策略对象并调用策略的方法。

示例:

假设你有一个电商平台,根据用户的等级(普通用户、会员、VIP)给予不同的折扣。我们可以使用策略模式来实现不同的折扣逻辑。

1、定义策略接口

// 策略接口,定义计算折扣的方法
public interface IDiscountStrategy
{
    decimal CalculateDiscount(decimal price);
}

2、实现具体的策略类

// 普通用户的折扣策略:无折扣
public class NoDiscountStrategy : IDiscountStrategy
{
    public decimal CalculateDiscount(decimal price)
    {
        return price; // 无折扣
    }
}

// 会员的折扣策略:10% 折扣
public class MemberDiscountStrategy : IDiscountStrategy
{
    public decimal CalculateDiscount(decimal price)
    {
        return price * 0.9m; // 10% 折扣
    }
}

// VIP 的折扣策略:20% 折扣
public class VIPDiscountStrategy : IDiscountStrategy
{
    public decimal CalculateDiscount(decimal price)
    {
        return price * 0.8m; // 20% 折扣
    }
}

3、创建上下文

// 上下文类,用于选择和执行策略
public class ShoppingCart
{
    private IDiscountStrategy _discountStrategy;

    // 通过构造函数设置策略
    public ShoppingCart(IDiscountStrategy discountStrategy)
    {
        _discountStrategy = discountStrategy;
    }

    // 计算折扣后的价格
    public decimal CalculateTotalPrice(decimal price)
    {
        return _discountStrategy.CalculateDiscount(price);
    }
}

4、使用策略模式

public class Program
{
    public static void Main(string[] args)
    {
        decimal originalPrice = 100m; // 商品的原价

        // 普通用户
        IDiscountStrategy noDiscount = new NoDiscountStrategy();
        ShoppingCart cartForNormalUser = new ShoppingCart(noDiscount);
        Console.WriteLine($"普通用户的价格: {cartForNormalUser.CalculateTotalPrice(originalPrice)}");

        // 会员用户
        IDiscountStrategy memberDiscount = new MemberDiscountStrategy();
        ShoppingCart cartForMember = new ShoppingCart(memberDiscount);
        Console.WriteLine($"会员用户的价格: {cartForMember.CalculateTotalPrice(originalPrice)}");

        // VIP 用户
        IDiscountStrategy vipDiscount = new VIPDiscountStrategy();
        ShoppingCart cartForVIP = new ShoppingCart(vipDiscount);
        Console.WriteLine($"VIP 用户的价格: {cartForVIP.CalculateTotalPrice(originalPrice)}");
    }
}

运行结果:

普通用户的价格: 100
会员用户的价格: 90
VIP 用户的价格: 80

理解了策略模式后,开始设计搜索功能。

1、定义策略接口

        public interface ISearchStrategy
        {
            List<PatientData> ExecuteSearch();
        }

2、实现具体的策略类,由于搜索条件有可能同时满足,所以定义组合策略类

        /// <summary>
        /// 日期搜索
        /// </summary>
        public class DateSearchStrategy : ISearchStrategy
        {
            private DateTime _date1, _date2;
            public DateSearchStrategy(DateTime date1, DateTime date2)
            {
                _date1 = date1.Date;
                _date2 = date2.Date;
            }

            public List<PatientData> ExecuteSearch()
            {
                var list = PatientDataAccess.GetAllPatientArchives();

                var filteredList = list.Where(p =>
                {
                    DateTime inspectDate;
                    bool isValidDate = DateTime.TryParse(p.inspectDate, out inspectDate);
                    return isValidDate && inspectDate >= _date1 && inspectDate <= _date2;
                }).ToList();

                return filteredList;
            }
        }

        /// <summary>
        /// 病人姓名搜索
        /// </summary>
        public class PatientNameSearchStrategy : ISearchStrategy
        {
            private string _name;
            public PatientNameSearchStrategy(string name)
            {
                _name = name;
            }
            public List<PatientData> ExecuteSearch()
            {
                var list = PatientDataAccess.GetAllPatientArchives();

                var filteredList = list.Where(p =>
                {
                    //return p.Name == _name;         //不能用==,string为引用类型
                    return p.Name.Equals(_name);
                }).ToList();

                return filteredList;
            }
        }
        /// <summary>
        /// 医生姓名搜索
        /// </summary>
        public class DoctorNameSearchStrategy : ISearchStrategy
        {
            private string _name;
            public DoctorNameSearchStrategy(string name)
            {
                _name = name;
            }
            public List<PatientData> ExecuteSearch()
            {
                var list = PatientDataAccess.GetAllPatientArchives();

                var filteredList = list.Where(p =>
                {
                    return p.inspectdoctor.Equals(_name);
                }).ToList();

                return filteredList;
            }
        }

        /// <summary>
        /// 组合搜索
        /// </summary>
        public class CompositeSearchStrategy : ISearchStrategy
        {
            private readonly List<ISearchStrategy> _strategies = new List<ISearchStrategy>();

            public void AddStrategy(ISearchStrategy strategy)
            {
                _strategies.Add(strategy);
            }

            public List<PatientData> ExecuteSearch()
            {
                if (_strategies.Count == 0)         //没有条件达成,显示全部(看需求)。
                {
                    return PatientDataAccess.GetAllPatientArchives();
                }
                List<PatientData> resultList = _strategies[0].ExecuteSearch();  //获取第一结果

                for (int i = 1; i < _strategies.Count; i++)
                {
                    //求与余下结果的交集
                    resultList = resultList.Where(p1 => _strategies[i].ExecuteSearch().Any(p2 => p1.inspectNumber == p2.inspectNumber)).ToList();
                }

                return resultList;
            }
        }

3、定义上下文

        public class SearchService
        {
            /// <summary>
            /// 搜索服务
            /// </summary>
            /// <param name="startDate">开始日期</param>
            /// <param name="endDate">结束日期</param>
            /// <param name="patientName">病人名字</param>
            /// <param name="doctorName">医生姓名</param>
            /// <returns></returns>
            public List<PatientData> Search(string startDate, string endDate, string patientName, string doctorName)
            {
                var searchStrateay = new CompositeSearchStrategy();

                //根据输入条件选择

                if (!string.IsNullOrWhiteSpace(startDate) && !string.IsNullOrWhiteSpace(endDate))
                {
                    if (DateTime.Parse(startDate) > DateTime.Parse(endDate))
                    {
                        MessageBox.Show("开始时间需早于结束时间!");
                        return null;
                    }
                    searchStrateay.AddStrategy(new DateSearchStrategy(DateTime.Parse(startDate), DateTime.Parse(endDate)));
                }

                if (!string.IsNullOrWhiteSpace(patientName))
                {
                    searchStrateay.AddStrategy(new PatientNameSearchStrategy(patientName));
                }
                if (!string.IsNullOrWhiteSpace(doctorName))
                {
                    searchStrateay.AddStrategy(new DoctorNameSearchStrategy(doctorName));
                }

                return searchStrateay.ExecuteSearch();
            }
        }

4、狠狠的使用它

        /// <summary>
        /// 搜索功能实现
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSearch_Click(object sender, EventArgs e)
        {
            var searchService = new SearchService();
            var list = searchService.Search(tbStartDate.Text, tbEndDate.Text, cbPatientName.Text, cbDoctorName.Text);
            if (!(list == null))
            {
                list.Reverse();
                dataGridView1.AutoGenerateColumns = false;     //固定标题栏
                dataGridView1.DataSource = list;
                lblTotal.Text = "查询总数:" + dataGridView1.RowCount;
            }
        }
相关推荐
IT规划师4 小时前
开源 - Ideal库 - 常用枚举扩展方法(一)
开源·c#·.net core·ideal库·枚举转换
NetX行者10 小时前
.NET 9震撼来袭:基于.NET 8的五大功能亮点,引领开发新潮流
开发语言·microsoft·c#·.netcore
张某布响丸辣10 小时前
HTTP状态码详解
java·网络·python·网络协议·http·c#
飞舞的哈哈10 小时前
C# 有趣的小程序—桌面精灵详细讲解
c#
Skyshin3412 小时前
C# IEnumerator,IEnumerable ,Iterator
开发语言·c#
ling1s12 小时前
C#核心(7)索引器
开发语言·c#
LKID体13 小时前
win32com库基于wps对Word文档的基础操作
c#·word·wps
金蝶软件小李14 小时前
vector和docker的区别?
开发语言·docker·c#
金蝶软件小李16 小时前
图像处理椒盐噪声
开发语言·图像处理·算法·计算机视觉·c#
小吴同学·16 小时前
(实战)WebApi第13讲:怎么把不同表里的东西,包括同一个表里面不同的列设置成不同的实体,所有的给整合到一起?【前端+后端】、前端中点击标签后在界面中显示
c#·.netcore·.net core