CSharp: Factory Method Pattern in donet core 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #region Animal Hierarchy /* * Both the Dog and Tiger classes will * implement the IAnimal interface method. */ /// <summary> /// 工厂方法模式 Factory Method Pattern /// geovindu,Geovin Du eidt /// </summary> public interface IAnimal { void AboutMe(); } /// <summary> /// Dog class /// </summary> public class Dog : IAnimal { public void AboutMe() { Console.WriteLine( "The dog says: Bow-Wow.I prefer barking." ); } } /// <summary> /// Tiger class /// </summary> public class Tiger : IAnimal { public void AboutMe() { Console.WriteLine( "The tiger says: Halum.I prefer hunting." ); } } #endregion #region Factory Hierarchy /// <summary> /// Both DogFactory and TigerFactory will use this. /// </summary> public abstract class AnimalFactory { /* Remember the GoF definition which says "....Factory method lets a class defer instantiation to subclasses." Following method will create a Tiger or a Dog, but at this point it does not know whether it will get a dog or a tiger. It will be decided by the subclasses i.e.DogFactory or TigerFactory. So, the following method is acting like a factory (of creation). */ public abstract IAnimal CreateAnimal( string animalType); } /* * ConcreteAnimalFactory is used to create dogs or tigers * based on method parameter of CreateAnimal() method. */ /// <summary> /// /// </summary> public class ConcreteAnimalFactory : AnimalFactory { /// <summary> /// /// </summary> /// <param name="animalType"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> public override IAnimal CreateAnimal( string animalType) { if (animalType.Contains( "dog" )) { //Creating a Dog return new Dog(); } else if (animalType.Contains( "tiger" )) { //Creating a Dog return new Tiger(); } else { throw new ArgumentException( "You need to pass either a dog or a tiger as an argument." ); } } } #endregion |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /// <summary> /// 工厂方法模式 Factory Method Pattern /// geovindu,Geovin Du eidt /// </summary> /// <typeparam name="T"></typeparam> public interface IAsyncInit<T> { Task<T> InitAsync(); } /// <summary> /// /// </summary> public class Foo : IAsyncInit<Foo> { /*public*/ public Foo() { // await Task.Delay(1000); } // ↓↓ public async Task<Foo> InitAsync() { // some work here Console.WriteLine( "some work here" ); await Task.Delay(1000); return this ; // fluent } public static Task<Foo> CreateAsync() { var result = new Foo(); return result.InitAsync(); } } /// <summary> /// /// </summary> public static class AsyncFactory { public static async Task<T> Create<T>() where T : IAsyncInit<T>, new () { var result = await new T().InitAsync(); return result; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | /// <summary> /// 抽象工厂模式 Abstract Factory Pattern /// geovindu,Geovin Du eidt /// </summary> public interface IShape { void Draw(); } /// <summary> /// /// </summary> public class Square : IShape { public void Draw() => Console.WriteLine( "Basic square" ); } /// <summary> /// /// </summary> public class Rectangle : IShape { public void Draw() => Console.WriteLine( "Basic rectangle" ); } /// <summary> /// /// </summary> public class RoundedSquare : IShape { public void Draw() => Console.WriteLine( "Rounded square" ); } /// <summary> /// /// </summary> public class RoundedRectangle : IShape { public void Draw() => Console.WriteLine( "Rounded rectangle" ); } /// <summary> /// /// </summary> public enum Shape { Square, Rectangle } /// <summary> /// /// </summary> public abstract class ShapeFactory { public abstract IShape Create(Shape shape); } /// <summary> /// /// </summary> public class BasicShapeFactory : ShapeFactory { public override IShape Create(Shape shape) { switch (shape) { case Shape.Square: return new Square(); case Shape.Rectangle: return new Rectangle(); default : throw new ArgumentOutOfRangeException( nameof(shape), shape, null ); } } } /// <summary> /// /// </summary> public class RoundedShapeFactory : ShapeFactory { public override IShape Create(Shape shape) { switch (shape) { case Shape.Square: return new RoundedSquare(); case Shape.Rectangle: return new RoundedRectangle(); default : throw new ArgumentOutOfRangeException(nameof(shape), shape, null ); } } } /// <summary> /// /// </summary> public class Demo { public static ShapeFactory GetFactory( bool rounded) { if (rounded) return new RoundedShapeFactory(); else return new BasicShapeFactory(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /// <summary> /// 工厂方法模式 Factory Method Pattern /// geovindu,Geovin Du eidt /// </summary> /// <typeparam name="T"></typeparam> public interface IAsyncInit<T> { Task<T> InitAsync(); } /// <summary> /// /// </summary> public class Foo : IAsyncInit<Foo> { /*public*/ public Foo() { // await Task.Delay(1000); } // ↓↓ public async Task<Foo> InitAsync() { // some work here Console.WriteLine( "some work here" ); await Task.Delay(1000); return this ; // fluent } public static Task<Foo> CreateAsync() { var result = new Foo(); return result.InitAsync(); } } /// <summary> /// /// </summary> public static class AsyncFactory { public static async Task<T> Create<T>() where T : IAsyncInit<T>, new () { var result = await new T().InitAsync(); return result; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | /// <summary> /// 工厂方法模式 Factory Method Pattern /// geovindu,Geovin Du eidt /// </summary> public interface IHotDrink { void Consume(); } /// <summary> /// /// </summary> internal class Tea : IHotDrink { public void Consume() { Console.WriteLine( "This tea is nice but I'd prefer it with milk." ); } } /// <summary> /// /// </summary> internal class Coffee : IHotDrink { public void Consume() { Console.WriteLine( "This coffee is delicious!" ); } } /// <summary> /// /// </summary> public interface IHotDrinkFactory { IHotDrink Prepare( int amount); } /// <summary> /// /// </summary> internal class TeaFactory : IHotDrinkFactory { public IHotDrink Prepare( int amount) { Console.WriteLine($ "Put in tea bag, boil water, pour {amount} ml, add lemon, enjoy!" ); return new Tea(); } } /// <summary> /// /// </summary> internal class CoffeeFactory : IHotDrinkFactory { public IHotDrink Prepare( int amount) { Console.WriteLine($ "Grind some beans, boil water, pour {amount} ml, add cream and sugar, enjoy!" ); return new Coffee(); } } /// <summary> /// /// </summary> public class HotDrinkMachine { /// <summary> /// /// </summary> public enum AvailableDrink // violates open-closed { Coffee, Tea } private Dictionary<AvailableDrink, IHotDrinkFactory> factories = new Dictionary<AvailableDrink, IHotDrinkFactory>(); private List<Tuple< string , IHotDrinkFactory>> namedFactories = new List<Tuple< string , IHotDrinkFactory>>(); /// <summary> /// /// </summary> public HotDrinkMachine() { //foreach (AvailableDrink drink in Enum.GetValues(typeof(AvailableDrink))) //{ // var factory = (IHotDrinkFactory) Activator.CreateInstance( // Type.GetType("DotNetDesignPatternDemos.Creational.AbstractFactory." + Enum.GetName(typeof(AvailableDrink), drink) + "Factory")); // factories.Add(drink, factory); //} foreach ( var t in typeof (HotDrinkMachine).Assembly.GetTypes()) { if ( typeof (IHotDrinkFactory).IsAssignableFrom(t) && !t.IsInterface) { namedFactories.Add(Tuple.Create( t.Name.Replace( "Factory" , string .Empty), (IHotDrinkFactory)Activator.CreateInstance(t))); } } } /// <summary> /// /// </summary> /// <param name="type"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> public IHotDrink MakeDrink( string type) { switch (type) { case "tea" : return new TeaFactory().Prepare(200); case "coffee" : return new CoffeeFactory().Prepare(50); default : throw new ArgumentException( "type" ); } } /// <summary> /// /// </summary> /// <returns></returns> public IHotDrink MakeDrink() { Console.WriteLine( "Available drinks" ); for ( var index = 0; index < namedFactories.Count; index++) { var tuple = namedFactories[index]; Console.WriteLine($ "{index}: {tuple.Item1}" ); } while ( true ) { string s; if ((s = Console.ReadLine()) != null && int .TryParse(s, out int i) // c# 7 && i >= 0 && i < namedFactories.Count) { Console.Write( "Specify amount: " ); s = Console.ReadLine(); if (s != null && int .TryParse(s, out int amount) && amount > 0) { return namedFactories[i].Item2.Prepare(amount); } } Console.WriteLine( "Incorrect input, try again." ); } } //public IHotDrink MakeDrink(AvailableDrink drink, int amount) //{ // return factories[drink].Prepare(amount); //} } |
调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // Console.WriteLine( "***工厂方法模式 Factory Pattern Demo.***" ); Console.WriteLine( "***It's a modified version using method parameter(s).***\n" ); // Creating a factory that can produce animals AnimalFactory animalFactory = new ConcreteAnimalFactory(); // Creating a tiger using the Factory Method IAnimal tiger = animalFactory.CreateAnimal( "tiger" ); tiger.AboutMe(); //Now creating a dog. IAnimal dog = animalFactory.CreateAnimal( "dog" ); dog.AboutMe(); //抽象工厂模式 var basic = Demo.GetFactory( false ); var basicRectangle = basic.Create(Shape.Rectangle); basicRectangle.Draw(); var roundedSquare = Demo.GetFactory( true ).Create(Shape.Square); roundedSquare.Draw(); // instead var foo = Foo.CreateAsync(); // Foo.CreateAsync(); // or var foo2 = AsyncFactory.Create<Foo>(); // var machine = new HotDrinkMachine(); //var drink = machine.MakeDrink(HotDrinkMachine.AvailableDrink.Tea, 300); //drink.Consume(); IHotDrink drink = machine.MakeDrink(); drink.Consume(); Console.ReadKey(); |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 | ***工厂方法模式 Factory Pattern Demo.*** ***It's a modified version using method parameter(s).*** The tiger says: Halum.I prefer hunting. The dog says: Bow-Wow.I prefer barking. Basic rectangle Rounded square some work here some work here Available drinks 0: Tea 1: Coffee |
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
分类:
CSharp code
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!