善用设计模式改善我们丑陋的代码——策略模式

  有时候因为种种原因导致我们会写出很多丑陋的代码,比如赶工时,短暂性的偷懒,不会设计模式等等导致代码沉积,一个cs上万行代码这样场景是有发生,

当然这里也包括我。。。所以时间充裕一点之后就想重构一下,毕竟项目中的需求是不断变更的,面对需求变更,尽量做到最低限度的修改代码,最大化的扩充

新代码,还有一点就是不要过分的追求设计模式,做到适可为止,太设计模式了会导致类太多,不好管理,在项目开发中,其实仔细考虑一下,你会发现很多业

务逻辑都有相应的设计模式帮你优化,毕竟这些都是前辈们踩了无数的坑,经过无数的苦难留下来的智慧结晶。很多人列举设计模式都喜欢用生活中的例子,但

毕竟生活中的例子如何应用到项目中,对我们程序员来说还是比较抽象的,所以这里我就列举我们实际的业务逻辑场景。

一:实际场景介绍

我们在做千人千面的时候,为了防止各大邮箱服务商对我们的邮件营销内容做屏蔽处理,我们采用的策略就是众多模板库中随机抽取一封html样式表,然后结

合具体的商品列表生成完全不一样风格的营销内容邮件,争取最大可能的不被屏蔽,而用户自己通过我们系统做的营销邮件,我们又不能随机发送,而是用户生成

什么样的邮件,我们就发什么样的邮件,ok,现在这里就有两种策略场景了,两种场景的最终目的都是生成邮件内容,对吧。

1. 普通商家做营销活动的邮件,这种策略没什么好说的,是什么就发什么。

2.千人千面场景下的营销活动邮件,这种策略采用随机抽取的模式,

目前来说,我们就这两种场景,谁也指不定以后还会不会有其他的策略出来,所以有必要用策略模式玩一下。

二:构建UML

从vs2005开始就有一个强大的功能,根据cs文件自动生成uml类图,非常的直观也更容易的帮助我们设计更加合理的类图。

上面就是策略模式的uml图,各个策略类中都有一个Setup方法,用来设置email的内容,具体各个类中的代码如下:

<1> AbstractStrategy

    public abstract class AbstractStrategy
    {
        public abstract void Setup();
    }

<2> RandStrategy

    public class RandStrategy : AbstractStrategy
    {
        public override void Setup()
        {
            Console.WriteLine("千人千面模式下的邮件发送");
        }
    }

<3> StraightStrategy

    public class StraightStrategy : AbstractStrategy
    {
        public override void Setup()
        {
            Console.WriteLine("普通商家发送的邮件");
        }
    }

<4>StrategyContext

    public class StrategyContext
    {
        AbstractStrategy strategy = null;

        public void SetStrategy(AbstractStrategy strategy)
        {
            this.strategy = strategy;
        }

        public void Setup()
        {
            this.strategy.Setup();
        }
    }

<5> Program

    class Program
    {
        static void Main(string[] args)
        {
            StrategyContext context = new StrategyContext();

            //设置“随机策略“
            context.SetStrategy(new RandStrategy());

            context.Setup();

            //设置 ”直接发送“
            context.SetStrategy(new StraightStrategy());

            context.Setup();
        }
    }

最后我们运行一下:

上面就是一个最简单的策略模式,当我们设置不同的策略,就会执行相应的行为,实际当中,并不会这么简单,毕竟设计模式只是一个最优化的提炼,排除干扰看本质。

三:生产应用

首先生产中我们的AbstractSetup中的Setup方法肯定是要带有参数的,而不是简单的无参,如下:

    /// <summary>
    /// 短信,邮件,彩信设置模型
    /// </summary>
    public abstract class AbstractSetup
    {
        public abstract void Setup(LeafletEntity leaflet, DataRow row);
    }

然后直接赋值的逻辑也非常的简单,需要根据数据库中设置的业务逻辑判断。

   public class StraightSetup : AbstractSetup
    {
        public override void Setup(LeafletEntity leaflet, DataRow row)
        {
            //非顾问
            leaflet.Title = MySqlDbHelper.GetString(row, "title");

            leaflet.SMSContent = leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.短信) ? MySqlDbHelper.GetString(row, "content") : string.Empty;
            leaflet.EDMContent = leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.邮件) ? MySqlDbHelper.GetString(row, "content") : string.Empty;
            leaflet.MMSContent = leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.彩信) ? MySqlDbHelper.GetString(row, "content") : string.Empty;

            leaflet.SendSMSCount = Convert.ToInt32(row["sendcount"]);
        }
    }

接下来就是随机抽取逻辑,这个也是通过读取随机表来进行各种操作,简单的代码如下:

  public class RandSetup : AbstractSetup
    {
        EventMarketingBLLNew eventMarketingBLLNew = new EventMarketingBLLNew();

        public override void Setup(LeafletEntity leaflet, DataRow row)
        {
            var eventMarketingInfo = eventMarketingBLLNew.GetEventMarketingInfo(leaflet.MarketingID, leaflet.ShopID);

            if (eventMarketingInfo != null)
            {
                //“短信”和“邮件”信息
                var communicationInfo = eventMarketingInfo.EventmarketingSmsEdmContentList.OrderBy(m => Guid.NewGuid())
                                                          .FirstOrDefault();

                if (communicationInfo == null) return;

                if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.邮件))
                {
                    //第三步:动态生成邮件模板
                    var styleInfo = CacheUtil.GetRandomEmailStyle();

                    var tuple = new EdmDraftBoxBLL().GetEdmHtmlTitle(communicationInfo.EDMJson, styleInfo.StyleId);

                    leaflet.Title = tuple.Item1;
                    leaflet.EDMContent = tuple.Item2;
                    leaflet.Header = tuple.Item3;
                    leaflet.SendSMSCount = 1;
                }

                if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.短信))
                {
                    leaflet.SMSContent = communicationInfo.SMSContent;
                    leaflet.SendSMSCount = communicationInfo.SMSCount;
                }

                if (leaflet.CommunicationtypeEnum.HasFlag(CommunicationTypeEnum.彩信))
                {
                    leaflet.MMSContent = communicationInfo.MMSContent;
                }
            }
        }
    }

最后就是策略上下文:

    public class SetupContext
    {
        AbstractSetup abstractSetup = null;

        public void Set(AbstractSetup abstractSetup)
        {
            this.abstractSetup = abstractSetup;
        }

        public void Setup(LeafletEntity leaflet, DataRow row)
        {
            this.abstractSetup.Setup(leaflet, row);
        }
    }

好了,这个就是给大家演示的策略模式,简单来说就是一句话:针对同一命令或行为,不同的策略做不同的动作。

时间: 2024-12-28 11:55:29

善用设计模式改善我们丑陋的代码——策略模式的相关文章

(四)设计模式之PHP项目应用(策略模式:自动驾驶系统)

1 前言 关于策略模式的定义,模式组成,模式核心思想,模式架构图,程序架构等基础知识介绍.请先参考我的另外一篇博客<(三)设计模式之PHP项目应用(策略模式:商场收银系统)>:http://blog.csdn.net/clevercode/article/details/45722661. 2 项目应用 2.1 需求说明 某公司是福特和本田公司的金牌合作伙伴,现要求开发一套自动驾驶系统,只要汽车上安装该系统就可以实现无人驾驶,只用实现启动,转弯,停止功能即可.该系统可以在福特和本田车上使用.这

Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---策略模式之MiniDuckSimulator[转]

 1 2{<HeadFirst设计模式>之策略模式 } 3{ 本单元中的类为策略类           } 4{ 编译工具: Delphi7.0           } 5{ E-Mail : [email protected]   } 6 7unit uStrategy; 8 9interface1011type12  {飞行接口,及其实现类 }1314  IFlyBehavior = Interface(IInterface)15    procedure Fly;16  end;1718

(三)设计模式之PHP项目应用(策略模式:商场收银系统)

1 策略模式简介 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 2 模式组成 1)抽象策略角色(Strategy): 策略类,通常由一个接口或者抽象类实现. 2)具体策略角色(ConcreteStrategy): 包装了相关的算法和行为. 3)环境角色(Context): 持有一个策略类的引用,最终给客户端调用. 3 模式核心思想 策略模式是一种定义一些列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是

PHP设计模式系列(一):策略模式

策略模式 策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法.比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法.组成 抽象策略角色:策略类,通常由一个接口或者抽象类实现.    具体策略角色:包装了相关的算法和行为.    环境角色:持有一个策略类的引用,最终给客户端调用. 实现结构图 步骤 定义抽象角色类(定义好各个实现的共同抽象方法)    定义具体策略类(具体实现父类的共同方法)    定义环境角色

设计模式学习(十五) 策略模式

策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法,并且由客户端决定调用那个算法 本质: -- 分离算法,选择实现 开发中常见的场景: 代码实现: package strategy; public interface Strategy { public double getPrice(double standardPrice); } 策略接口 package strategy; public class NewCusto

设计模式学习笔记(四:策略模式)

1.1概述 方法是类中最重要的组成部分,一个方法的方法体由一系列语句构成,也就是说一个方法的方法体是一个算法.在某些设计中,一个类的设计人员经常可能涉及这样的问题:由于用户需求的变化,导致经常需要修改类中某个方法的方法体,即需要不断地变化算法.在这样的情况下可以考虑使用策略模式. 策略模式是处理算法不同变体的一种成熟模式,策略模式通过接口或抽象类封装算法的标识,即在接口中定义一个抽象方法,实现该接口的类将实现接口中的抽象方法.策略模式把针对一个算法标识的一系列具体算法分别封装在不同的类中,使得各

《大话设计模式学习笔记》2:策略模式

商场促销示例: 1.策略类: public abstract class CashSuper { public abstract double AcceptCash(double money); } 2.具体策略类(以打折类为例): public class CashRebate:CashSuper { private double moneyRebate; public CashRebate(double moneyRebate) { this.moneyRebate = moneyRebat

设计模式学习总结(八)策略模式(Strategy)

策略模式,主要是针对不同的情况采用不同的处理方式.如商场的打折季,不同种类的商品的打折幅度不一,所以针对不同的商品我们就要采用不同的计算方式即策略来进行处理. 一.示例展示: 以下例子主要通过对手机和笔记本添加不同的策略来实现策略模式的应用! 1. 创建抽象策略角色:DailyProductStrategy abstract class DailyProductStrategy { public abstract void AlgorithmInterface(); } 2. 创建具体策略角色:

大话设计模式C++实现-第2章-策略模式

一.UML图 二.概述 策略模式:他定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 三.优点 (1)策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,他可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合. (2)策略模式的Strategy类曾是为Context定义了一些列的可供重用的算法或行为.集成有助于析取出这些算法中的公共功能. (3)策略模式简化了单元测试,因为每个算法