• 如何编写优雅的代码:07. 设计模式应用案例(下)


    前文用C#代码实现了Facade模式、Adapter模式、Strategy模式、Bridge模式和Abstract Factory模式解决实际业务需求。本文将继续以C#代码为例,实现我在前面介绍的11个模式中剩下的6个模式:Decorator模式、Observer模式、Template Method模式、Singleton模式、Factory Method模式和Prototype模式。按照实现方法的不同,该11个模式可分成三类:创建型模式(Abstract Factory, Singleton, Factory Method, Prototype)、结构型模式(Adapter, Bridge, Decorator)和行为型模式(Strategy, Observer, Template Method)。

    .Decorator模式

    业务场景:在中国销售的一块手表,基本配置是显示北京时间,但也提供带有高级功能的配置。如:中端配置支持显示当前时区下的日期、高端配置支持第二时区(具体可以用户设置)。采用Decorator模式实现的代码如下:

    namespace PartternCase
    {
        public abstract class AbstractWatch
        {//Component in UML
            public abstract void StartWork();
        }
    
        public class Watch : AbstractWatch
        {//ConcreteComponent in UML
            public override void StartWork()
            {
                //Show Beijing time
            }
        }
    
        public abstract class WatchDecorator : AbstractWatch
        {//Decorator in UML
            protected AbstractWatch Watch { get; set; }
            protected WatchDecorator(AbstractWatch watch)
            {
                Watch = watch;
            }
        }
    
        public class ShowDateDecorator : WatchDecorator
        {//ConcreteDecoratorA in UML
            public ShowDateDecorator(AbstractWatch watch)
                : base(watch)
            {
            }
    
            public override void StartWork()
            {
                Watch.StartWork();
                //Show date of current time zone
            }
        }
    
        public class ShowSecTimeZoneDecorator : WatchDecorator
        {//ConcreteDecoratorB in UML
            public ShowSecTimeZoneDecorator(AbstractWatch watch)
                : base(watch)
            {
            }
    
            public override void StartWork()
            {
                Watch.StartWork();
                // Show time of sencond timezone
            }
        }
    
        public class Client
        {//How to use decorator pattern
            public void ChooseWatch()
            {
                var watch = new Watch();//Basic function
                var middleWatch = new ShowDateDecorator(watch);//Middle: contain show date function
                var advanceWatch = new ShowSecTimeZoneDecorator(middleWatch);//Advance: contain show date and second time zone function
            }
        }
    }

    .Observer模式

    业务场景:盛天公司内部的报销有严格的审批流程,为提高审批效率,当员工提交报销单时,需要向具有审批权限的领导自动发送申请审批的邮件(当然,除报销单外,领导还会收到其他类型的审批邮件)。采用Observer模式实现的代码如下:

    namespace PartternCase
    {
        public abstract class Report
        {//Subject in UML
            public string Status { get; set; }
            protected IList<Employee> Employees { get; set; }
            public void Attach(Employee employee)
            {
                Employees = Employees ?? new List<Employee>();
                Employees.Add(employee);
            }
    
            public void Detach(Employee employee)
            {
                if (Employees == null) { return; }
                Employees.Remove(employee);
            }
    
            public void Notify(Report report)
            {
                if (Employees == null) { return; }
                foreach (var employee in Employees)
                {
                    employee.HandleReportSubmit(report);
                }
            }
        }
    
        public class ExpenseReport : Report
        {//ConcreteSubject in UML
            public void Submit()
            {
                Status = "Report Submited";
                Notify(this);
            }
        }
    
        public abstract class Employee
        {//Observer in UML
            public abstract void HandleReportSubmit(Report report);
        }
    
        public class Boss : Employee
        {//ConcreteObserver in UML
            public string Status { get; set; }
            public override void HandleReportSubmit(Report report)
            {
                // Send email to this boss by smtp server
                Status = report.Status;
            }
        }
    
        public class Client
        {//How to use observer pattern
            public void Observer()
            {
                var boss1 = new Boss();
                var boss2 = new Boss();
                var expense = new ExpenseReport();
                expense.Attach(boss1);
                expense.Attach(boss2);
                expense.Submit();
            }
        }
    }

    .Template Method模式

    业务场景:圣象饮料公司生产牛奶和矿泉水两种饮料。运营过程都分为生产和销售两个环节,但两种饮料的生产和销售方式不相同。如销售方式:牛奶每天通过送货员送货上门,矿泉水通过各大超市销售。采用Template Method模式实现的代码如下:

    namespace PartternCase
    {
        public abstract class DrinkOperation
        {//AbstractClass in UML
            public void Perform()
            {//Interface for client call
                Product();
                Sales();
            }
    
            protected abstract void Product();
            protected abstract void Sales();
        }
    
        public class MilkOperation : DrinkOperation
        {//ConcreteClass in UML
            protected override void Product()
            {
                //Get raw material from milk station then process 
            }
    
            protected override void Sales()
            {
                //Sell by deliveryman
            }
        }
    
        public class WaterOperation : DrinkOperation
        {//ConcreteClass in UML
            protected override void Product()
            {
                //Get raw material from mountain then process 
            }
    
            protected override void Sales()
            {
                //Sell by supermarket
            }
        }
    }

    . Singleton模式

    业务场景:投资组合管理系统中经常会用到一些复杂的模型对投资组合的价值进行估值。这些计算模型往往都放在一个类中,互相之间没有依赖关系。采用Singleton模式实现的代码如下:

    namespace PartternCase
    {
        public class CalculationEngine
        {//Singleton in UML
            protected CalculationEngine() { }
    
            private static readonly CalculationEngine instance = new CalculationEngine();
            public static CalculationEngine GetInstance { get { return instance; } }// Interface for client call
    
            //Many calculation methods
        }
    }

    . Factory Method模式

    业务场景:圣天基金公司旗下的基金在向合伙人提款时,需根据合伙人类型不同(普通合伙人:GP、有限合伙人:LP)将提款数据存放在相应的合伙人类型中,然后保存。采用Factory Method模式实现的代码如下:

    namespace PartternCase
    {
        public abstract class CapitalCall
        {//Creator in UML
            public abstract Partner BuildPartner();
    
            public void Perform()
            {
                var partner = BuildPartner();
                //Calculate amount of partner then save partner
            }
        }
    
        public class GpCapitalCall : CapitalCall
        {//ConcreteCreator in UML
            public override Partner BuildPartner()
            {
                return new GP();
            }
        }
    
        public class Partner
        {//Product in UML
            public decimal Amount { get; set; }
        }
    
        public class GP : Partner
        {//ConcreteProduct in UML
        }
    }

    . Prototype模式

    业务场景:圣象饮料公司在查询牛奶和矿泉水的季度销量时,会分别针对Milk和Water数据库表进行查询,查询条件除时间外从外部传入,内部只设置时间条件,但不能改变传入的查询条件。下面将采用Prototype模式实现该业务场景:

    namespace PartternCase
    {
        public abstract class DrinkCriteria
        {//Prototype in UML
            public abstract string QueryTable { get; }
            public DateTime StartDate { get; set; }
            public DateTime EndDate { get; set; }
            //Other query fields
    
            public abstract DrinkCriteria Clone();
        }
    
        public class MilkCriteria : DrinkCriteria
        {//Concrete Prototype1 in UML
            public override string QueryTable { get { return "Milk"; } }
    
            public override DrinkCriteria Clone()
            {//This is shallow copy, in other case maybe need deep copy.
                return MemberwiseClone() as MilkCriteria;
            }
        }
    
        public class WaterCriteria : DrinkCriteria
        {//Concrete Prototype2 in UML
            public override string QueryTable { get { return "Water"; } }
    
            public override DrinkCriteria Clone()
            {
                return MemberwiseClone() as WaterCriteria;
            }
        }
    
        public class Client
        {//Client in UML
            //Set relative criteria at runtime
            private DrinkCriteria Criteria { get; set; }
            public void HowToUse()
            {
                var newCritera = Criteria.Clone();
                //newCritera.StartDate = 2013-1-1;
                //newCritera.EndDate = 2013-3-31;
                //Start to query user new criteria
            }
        }
    }
  • 相关阅读:
    Fragments (Android官方文档中文版)
    Fragment and activity的生命周期对比和区别
    frida报错frida.InvalidArgumentError: device not found问题解决方案
    XCTF---easyjava的WriteUp
    XCTF---easyjni的WriteUp
    日常破解--从XCTF的app3题目简单了解安卓备份文件以及sqliteCipher加密数据库
    Anroid关于fragment控件设置长按事件无法弹出Popupwindows控件问题解决记录
    DEX文件解析---2、Dex文件checksum(校验和)解析
    日常破解--XCTF easy_apk
    日常破解---XCTF_APP1获取flag记录
  • 原文地址:https://www.cnblogs.com/zhouwei0213/p/3358224.html
Copyright © 2020-2023  润新知