抽象 了实例化 过程。
工厂方法 Factory Method
工厂方法的意图
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
具体实现
如果不用工厂方法,我们如何实现?
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 public class Wand { public string Name { get ; set ; } } public class FireWand : Wand { public FireWand () { Name = "Fire Wand" ; } } public class IceWand : Wand { public IceWand () { Name = "Ice Wand" ; } } int main (){ var fireWand = new FireWand(); var iceWand = new IceWand(); }
如果我们需要一个新的魔杖,我们需要实现一个新的魔杖类,然后实现一个新的方法,这样就会导致类的爆炸。
如果某一个魔杖需要求修改,那么需要全局搜索,修改所有的地方。
如果我们使用工厂方法,我们可以这样实现:
swtich case (简单工厂)
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 public enum WandType{ Fire, Ice } public class Wand { public string Name { get ; set ; } } public class WandFactory { public Wand CreateWand (WandType type ) { switch (type) { case WandType.Fire: return new Wand { Name = "Fire Wand" }; case WandType.Ice: return new Wand { Name = "Ice Wand" }; default : throw new ArgumentOutOfRangeException(nameof (type), type, null ); } } } int main (){ var factory = new WandFactory(); var fireWand = factory.CreateWand(WandType.Fire); var iceWand = factory.CreateWand(WandType.Ice); }
降低了客户端(调用者)和具体产品类的耦合度。然而违背了开闭原则,如果我们需要增加一个新的魔杖,我们需要修改工厂类。
泛型类
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 public enum WandType{ Fire, Ice } public class Wand { protected string Name { get ; set ; } = "Wand" ; } public class FireWand : Wand { public FireWand () { Name = "Fire Wand" ; Console.WriteLine("生产了" +Name); } } public class IceWand : Wand { public IceWand () { Name = "Ice Wand" ; Console.WriteLine("生产了" +Name); } } public class WandFactory <T > where T : Wand , new (){ public T CreateWand () { return new T(); } } public class Program { public static void Main (string [] args ) { var iceWandFactory = new WandFactory<IceWand>(); var wand = iceWandFactory.CreateWand(); var fireWandFactory = new WandFactory<FireWand>(); var wand2 = fireWandFactory.CreateWand(); } }
可以使用 where : Wand, new() 来限制泛型类型。
tips: new() 限制泛型类型必须有无参构造函数。
泛型方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 interface IWandFactoryMethod { Wand CreateWand <T >() where T : Wand, new () ; } public class WandFactory : IWandFactoryMethod { public Wand CreateWand <T >() where T : Wand, new () { return new T(); } } public class Program { public static void Main (string [] args ) { var wandFactory = new WandFactory(); var wand = wandFactory.CreateWand<IceWand>(); var wand2 = wandFactory.CreateWand<FireWand>(); } }
三点好处: 1. 拥有工厂接口 2. 可以限制传入产品,并且在编译期间就可以发现 3. 免去 switch case 的判断
抽象工厂 Abstract Factory
抽象工厂的意图
提供一个接口,用于创建相关或依赖对象的家族 ,而不需要明确指定具体类。
具体实现
抽象工厂
具体工厂
抽象产品
具体产品
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 public enum magicType{ Fire, Ice } public abstract class Wand { protected string Name { get ; set ; } = "Wand" ; } public abstract class Sword { protected string Name { get ; set ; } = "Sword" ; } public class FireSword : Sword { public FireSword () { Name = "Fire Sword" ; Console.WriteLine("生产了" +Name); } } public class IceSword : Sword { public IceSword () { Name = "Ice Sword" ; Console.WriteLine("生产了" +Name); } } public class FireWand : Wand { public FireWand () { Name = "Fire Wand" ; Console.WriteLine("生产了" +Name); } } public class IceWand : Wand { public IceWand () { Name = "Ice Wand" ; Console.WriteLine("生产了" +Name); } } public abstract class AbstractFactory { public abstract Wand CreateWand () ; public abstract Sword CreateSword () ; } public class FireFactory : AbstractFactory { public override Wand CreateWand () { return new FireWand(); } public override Sword CreateSword () { return new FireSword(); } } public class IceFactory : AbstractFactory { public override Wand CreateWand () { return new IceWand(); } public override Sword CreateSword () { return new IceSword(); } } public class Program { static void Main (string [] args ) { AbstractFactory factory = new FireFactory(); factory.CreateSword(); factory.CreateWand(); } }
缺点
如果我们需要增加一个新的产品,比如 Shield,那么我们需要修改 AbstractFactory,这样就违背了开闭原则。
工厂方法的非单例实现
静态类和静态方法
参考是在设计模式与完美游戏开发的 201-202 页
生成器 Builder
生成器的意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
当一个类的构造函数参数个数超过 4 个,而且这些参数有些是可选的参数,考虑使用构造者模式。
流程分析安排 Director
功能分开实现 Builder
流水线,流程分析
同样的流程,每一步做不一样的事情,结果也不同
生成器的具体实现
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 public class Potion { private List<string > parts = new List<string >(); public Potion () {} public void Add (string part ) { parts.Add(part); } public void Show () { Console.WriteLine("\nPotion completed as below :" ); foreach (string part in parts) Console.WriteLine(part); } } public class Director { private Potion potion; public Director () {} public void Construct (Builder theBuilder ) { potion = new Potion(); theBuilder.BuildPartA(potion); theBuilder.BuildPartB(potion); theBuilder.BuildPartC(potion); potion = GetProduct(); } public Potion GetProduct () { return potion; } } public abstract class Builder { public abstract void BuildPartA (Object part ) ; public abstract void BuildPartB (Object part ) ; public abstract void BuildPartC (Object part ) ; } public class PotionBuilder : Builder { public override void BuildPartA (Object product ) { (product as Potion).Add("瓶子" ); } public override void BuildPartB (Object product ) { (product as Potion).Add("水" ); } public override void BuildPartC (Object product ) { (product as Potion).Add("药剂" ); } } public class Program { public static void Main (string [] args ) { Director director = new Director(); Potion product = null ; Builder builder = new PotionBuilder(); director.Construct(builder); product = director.GetProduct(); product.Show(); } }
单例 Singleton
单例的意图
提供一个全局 访问点来获取唯一 的实例。
也即其使用的范围 -> 全局 + 唯一的
单例的具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Singleton { private static Singleton _instance; private Singleton () { } public static Singleton GetInstance () { if (_instance == null ) { _instance = new Singleton(); } return _instance; } } public class Foo { public static Foo instance { get ; } = new Foo(); }
Unity 中的单例值得注意的点 => monobeheviour
1 2 3 4 5 6 7 8 9 public class GameManager : MonoBehaviour { public static GameManager Instance; private void Awake () { Instance = this ; } }
单例模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Singleton <T > where T : new (){ private static T _instance; private static readonly object _lock = new object (); protected Singleton () { } public static T GetInstance () { if (_instance == null ) { lock (_lock) { if (_instance == null ) { _instance = new T(); } } } return _instance; } }
参考
【Sast C# Class 4.1 泛型-类型系统的万金油】https://www.bilibili.com/video/BV1dQ4y1b766?vd_source=91b4ae86004267b4d5aa5f0c99c21e95