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

2021-08-02  本文已影响0人  码农猫爸

辨析的背景

单产品(变形1)

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)

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)

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)

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();
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读