CSharp: Factory Method Pattern in donet core 3
#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
/// <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;
}
}
/// <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();
}
}
/// <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;
}
}
/// <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);
//}
}
调用:
//
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();
输出:
***工厂方法模式 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(涂聚文)
浙公网安备 33010602011771号