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

前文一共介绍了四人帮(Gang of Four)总结的的11个设计模式,对初学者而言,光看文字描述和UML类图略显抽象。本着Learning in Doing的原则,本文将举一些实际的业务需求场景,以C#代码为例,讲述在编程的过程中如何应用设计模式,实现模块间低耦合,高内聚,编写出优雅的代码。需说明的是,接下来的例子相对简单,省略了业务逻辑代码,目的是为了让大家专注于设计模式的应用,忽略业务逻辑本身的复杂性,毕竟本文的目的是加深对设计模式本身的理解。

一.Façade模式

业务场景:圣象饮料公司需汇总每个季度矿泉水的销量,并和竞争对手的销量进行比较,并且以季度报表的形式汇报管理层。当前的系统情况是:统计内部商品的销量由类SelfProduct、竞争对手商品的销量由类CompetitorProject负责,该需求用Facade模式实现如下:

namespace PartternCase
{
    public class SelfProduct
    {//Class A in UML
        public decimal StatSales(DateTime start, DateTime end, string kind);
    }

    public class CompetitorProduct
    {//Class B in UML
        public decimal StatSales(DateTime start, DateTime end, string kind);
    }

    public class ReportFacade
    {//Facade in UML
        private SelfProduct Self { get; set; }
        private CompetitorProduct Competitor { get; set; }

        public ReportFacade(SelfProduct self, CompetitorProduct competitor)
        {
            Self = self;
            Competitor = competitor;
        }

        public Tuple<decimal, decimal> StatSelling(DateTime start, DateTime end)
        {//Interface for client call
            return Tuple.Create(Self.StatSales(start, end, "MineralWater"), Competitor.StatSales(start, end, "MineralWater"));
        }
    }
}

二.Adapter模式

业务场景:需要提供一个快速创建Word文档的API,微软提供的Office对象模型太复杂,创建Word时需要传入太多的缺省参数。下面是用对象Adapter模式实现的代码(C#不支持多继承,在此不介绍类Adapter模式,况且也不推荐使用):

namespace PartternCase
{
    public interface IWordAdapter
    {//Target in UML
        //Interface for client call
        void CreateWord(string filePath);
    }

    public class WordAdapter : IWordAdapter
    {//Adapter in UML
        public void CreateWord(string filePath)
        {
            Object Nothing = System.Reflection.Missing.Value;
            //MS default word creator is Adaptee
            Application wordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            Document wordDoc = wordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing);
            wordDoc.SaveAs(ref filePath, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, 
                ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing);
            wordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
            wordApp.Quit(ref Nothing, ref Nothing, ref Nothing);
        }
    }
}

三.Strategy模式

业务场景:假设用户熟悉每种排序算法的应用场景,需要在界面自己选择排序算法(众所周知,排序算法有很多种,各自适合不同的场景),将一组数字排序后,打印在窗口。采用策略模式实现的代码如下:

namespace PartternCase
{
    public class SequencePrinter
    {//Context in UML
        private Sorter Sorter { get; set; }

        public SequencePrinter(Sorter sorter)
        {//Interface for client call
            Sorter = sorter;
        }

        public void Perform(IList<int> sequences)
        {//Assign relative sorter by criteria at runtime context
            sequences = Sorter.Rank(sequences);
            foreach (var sequence in sequences)
            {
                Console.WriteLine("Number is " + sequence);
            }
        }
    }

    public abstract class Sorter
    {//Strategy in UML
        public abstract IList<int> Rank(IList<int> source);
    }

    public class BubbleSorter : Sorter
    {//ConcreteStrategyA in UML 
        public override IList<int> Rank(IList<int> source);
    }

    public class QuickSorter : Sorter
    {//ConcreteStrategyB in UML
        public override IList<int> Rank(IList<int> source);
    }
}

四.Bridge模式

业务场景:将上述Strategy模式的业务场景做一个扩展,正好就是采用Bridge模式的最佳场景,即:用户可以在界面选择外排序算法和打印终端,将一组数据排序后,打印到相应的终端上。采用Bridge模式的实现代码如下:

namespace PartternCase
{
    public abstract class AbstractSequencePrinter
    {//Abstraction in UML
        protected Sorter Sorter { get; set; }

        protected AbstractSequencePrinter(Sorter sorter)
        {//Assign relative sorter by criteria at runtime context
            Sorter = sorter;
        }

        public abstract void Perform(IList<int> sequences);
    }

    public class ConsoleSequencePrinter : AbstractSequencePrinter
    {//RefinedAbstraction in UML
        public ConsoleSequencePrinter(Sorter sorter)
            : base(sorter)
        {
        }

        public override void Perform(IList<int> sequences)
        {
            sequences = Sorter.Rank(sequences);
            foreach (var sequence in sequences)
            {
                Console.WriteLine("Number is " + sequence);
            }
        }
    }

    public abstract class Sorter
    {//Implementor in UML
        public abstract IList<int> Rank(IList<int> source);
    }

    public class BubbleSorter : Sorter
    {//ConcreteImplementorA in UML
        public override IList<int> Rank(IList<int> source);
    }

    public class QuickSorter : Sorter
    {//ConcreteImplementorB in UML
        public override IList<int> Rank(IList<int> source);
    }
}

五.Abstract Factory模式

业务场景:圣天基金公司旗下有两种私募基金产品:主基金(Master Fund)和子基金(Feeder Fund)。两种基金的提款(Capital Call)规则和分配(Distribution)规则都存在明显差异,要求主基金的提款规则只能和主基金的分配规则搭配使用,不允许混淆。采用Abstract Factory模式的实现代码如下:

namespace PartternCase
{
    public abstract class AbstractFund
    {//Abstract Factory
        //Interface for client call
        public abstract CapitalCallRule CreateCallRule();
        public abstract DistributionRule CreateDistribRule();
    }

    public class MasterFund : AbstractFund
    {//ConcreteFactory1 in UML
        public override CapitalCallRule CreateCallRule()
        {
            return new MasterCallRule();
        }

        public override DistributionRule CreateDistribRule()
        {
            return new MasterDistribRule();
        }
    }

    public class FeederFund : AbstractFund
    {//ConcreteFactory2 in UML
        public override CapitalCallRule CreateCallRule()
        {
            return new FeederCallRule();
        }

        public override DistributionRule CreateDistribRule()
        {
            return new FeederDistribRule();
        }
    }

    public abstract class CapitalCallRule
    {//AbstractProductA in UML
    }

    public class MasterCallRule : CapitalCallRule
    {//ConcreteProductA1 in UML
    }

    public class FeederCallRule : CapitalCallRule
    {//ConcreteProductA2 in UML
    }

    public abstract class DistributionRule
    {//AbstractProductB in UML
    }

    public class MasterDistribRule : DistributionRule
    {//ConcreteProductB1 in UML
    }

    public class FeederDistribRule : DistributionRule
    {//ConcreteProductB2 in UML
    }
}
原文地址:https://www.cnblogs.com/zhouwei0213/p/3355241.html