美文网首页
{C#}设计模式辨析.工厂方法

{C#}设计模式辨析.工厂方法

作者: 码农猫爸 | 来源:发表于2021-08-02 17:16 被阅读0次

    辨析的背景

    单产品(变形1)

    • 最简代码,个人代码中常见
    • 无法应对同类产品的增加,产品不变时OK
    using static System.Console;
    
    namespace SingleProduct
    {
        public class Pencil
        {
            public void Make() => WriteLine("One pencil is made.");
        }
    
        public class Client
        {
            private Pencil pencil = new Pencil();
    
            public void Execute() => pencil.Make();
        }
    
        class Demo
        {
            // 单一产品时无需接口,最简代码也可运行
            static void Main(string[] args)
            {
                var client = new Client();
                client.Execute();
            }
        }
    }
    

    同类多产品(变形2)

    • 接口实现同类产品互换,可应对产品的增加
    • 不能选择某个产品生产,产品不变且全部生产时OK
    using static System.Console;
    
    namespace AllProducts
    {
        interface IStationery { void Make(); }
    
        public class Pencil : IStationery
        {
            public void Make() => WriteLine("One pencil is made.");
        }
    
        public class Knife : IStationery
        {
            public void Make() => WriteLine("One Knife is made.");
        }
    
        public class Client
        {
            // 多个类似产品,接口可保证互换性
            private IStationery stationery;
    
            // 生产所有产品
            public void Execute()
            {
                stationery = new Pencil();
                stationery.Make();
    
                stationery = new Knife();
                stationery.Make();
            }
        }
    
        class Demo
        {
            static void Main(string[] args)
            {
                var client = new Client();
                client.Execute();
            }
        }
    }
    

    简单工厂(变形3)

    • 同类多产品基础上,可选产品生产
    • 违背单一职责(SRP)原则,直接NG
    • 优势:调用时省略了生成细节
    • 要点:引入分支判断
    using System;
    using static System.Console;
    
    namespace SimpleFactory
    {
        // 省略文具接口和其子类,见同类多产品
        public class Client
        {
            public void Execute(string name)
            {
                // 多个类似产品,接口可保证互换性
                IStationery stationery;
    
                // 按品名生产
                switch (name)
                {
                    case "pencil":
                        stationery = new Pencil();
                        break;
    
                    case "knife":
                        stationery = new Knife();
                        break;
    
                    default:
                        throw new Exception("无此产品");
                }
    
                stationery.Make();
            }
        }
    
        class Demo
        {
            static void Main(string[] args)
            {
                // 如需生产橡皮,应
                // - 增加IStationery的子类Rubber,不影响旧代码
                // - 增加Client中分支语句,影响旧代码(不符合单一职责,NG)
                // - 修改本类中品名,影响旧代码(必须)
                var client = new Client();
                client.Execute("pencil");
            }
        }
    }
    

    工厂方法(变形4)

    • 简单工厂基础上,遵守单一职责(SRP)原则
    • 要点:具体工厂中通过重写接口方法(模式得名)绑定同类具体产品,不接受产品传参
    using static System.Console;
    
    namespace FactoryMethod
    {
        // 省略文具接口和其子类,见同类多产品
        public interface IFactory { IStationery CreateStationery(); }
    
        public class PencilFactory : IFactory
        {
            // 工厂与产品已绑定,调用时仅关注工厂即可
            public IStationery CreateStationery() => new Pencil();
        }
    
        public class KnifeFactory : IFactory
        {
            public IStationery CreateStationery() => new Knife();
        }
    
        public class Client
        {
            // 多个类似工厂,接口可保证互换性
            private readonly IFactory factory;
    
            public Client(IFactory factory)
            {
                this.factory = factory;
            }
    
            public void Execute()
            {
                var stationery = factory.CreateStationery();
                stationery.Make();
            }
        }
    
        class DesignPattern
        {
            static void Main(string[] args)
            {
                // 如需生产橡皮,应
                // - 增加IStationery的子类Rubber,不影响旧代码
                // - 增加IFactory的子类RubberFactory,不影响旧代码
                // - 修改本类中工厂,影响旧代码(必须)
                var factory = new PencilFactory();
                var client = new Client(factory);
                client.Execute();
            }
        }
    }
    

    奇怪的工厂(变形5)

    • 工厂方法基础上,合并了工厂子类,违背了不关心生成细节的初心
    using static System.Console;
    
    namespace OddFactory
    {
        // 省略接口IStationery, 子类Pencil & Knife
        public class Factory
        {
            // 工厂未绑定产品
            private readonly IStationery stationery;
    
            public Factory(IStationery stationery)
            {
                this.stationery = stationery;
            }
    
            public void Make() => stationery.Make();
        }
    
        public class Client
        {
            private readonly Factory factory;
    
            public Client(Factory factory)
            {
                this.factory = factory;
            }
    
            public void Execute() => factory.Make();
        }
    
        class Demo
        {
            static void Main(string[] args)
            {
                // - 违背了工厂方法的初心,不应关注生成细节
                // - 增加了代码层次和理解难度
                var pencil = new Pencil();
                var factory = new Factory(pencil);
                var client = new Client(factory);
                client.Execute();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:{C#}设计模式辨析.工厂方法

          本文链接:https://www.haomeiwen.com/subject/uxyevltx.html