{"id":693,"date":"2025-04-12T16:11:54","date_gmt":"2025-04-12T08:11:54","guid":{"rendered":"https:\/\/www.hyy.net\/?p=693"},"modified":"2025-04-12T16:11:54","modified_gmt":"2025-04-12T08:11:54","slug":"net-7-design-patterns-in-depth-2-creational-design-patterns","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=693","title":{"rendered":"NET 7 Design Patterns In-Depth 2. Creational Design Patterns"},"content":{"rendered":"<p>Chapter 2 Creational Design Patterns<br \/>\n\u7b2c2\u7ae0 \u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<\/p>\n<h2>Introduction<\/h2>\n<h2>\u7b80\u4ecb<\/h2>\n<p>As the name suggests, creational design patterns deal with object construction and how to create instances. In C# .NET programming language, a new keyword is used to create an object. To create an object, it is necessary to provide the name of the class. In other words, wherever an object is needed, it can be created using the new keyword and the class name. However, there are instances where it is necessary to hide the way the object is made from the user's view. In this case, creational design patterns can be useful.<\/p>\n<p>\u987e\u540d\u601d\u4e49\uff0c\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f\u5904\u7406\u5bf9\u8c61\u6784\u9020\u4ee5\u53ca\u5982\u4f55\u521b\u5efa\u5b9e\u4f8b\u3002\u5728 C# .NET \u7f16\u7a0b\u8bed\u8a00\u4e2d\uff0cnew \u5173\u952e\u5b57\u7528\u4e8e\u521b\u5efa\u5bf9\u8c61\u3002\u8981\u521b\u5efa\u5bf9\u8c61\uff0c\u5fc5\u987b\u63d0\u4f9b\u7c7b\u7684\u540d\u79f0\u3002\u6362\u53e5\u8bdd\u8bf4\uff0c\u53ea\u8981\u9700\u8981\u5bf9\u8c61\uff0c\u5c31\u53ef\u4ee5\u4f7f\u7528 new \u5173\u952e\u5b57\u548c\u7c7b\u540d\u6765\u521b\u5efa\u5b83\u3002\u4f46\u662f\uff0c\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u6709\u5fc5\u8981\u4ece\u7528\u6237\u7684\u89c6\u56fe\u4e2d\u9690\u85cf\u5bf9\u8c61\u7684\u521b\u5efa\u65b9\u5f0f\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f\u53ef\u80fd\u5f88\u6709\u7528\u3002<\/p>\n<h2>Structure<\/h2>\n<h2>\u7ed3\u6784<\/h2>\n<p>In this chapter, we will cover the following topics:<\/p>\n<p>\u5728\u672c\u7ae0\u4e2d\uff0c\u6211\u4eec\u5c06\u4ecb\u7ecd\u4ee5\u4e0b\u4e3b\u9898\uff1a<\/p>\n<ul>\n<li>\n<p>Creational design pattern<br \/>\n\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<\/p>\n<\/li>\n<li>\n<p>Factory method<br \/>\n\u5de5\u5382\u65b9\u6cd5<\/p>\n<\/li>\n<li>\n<p>Abstract factory<br \/>\n\u62bd\u8c61\u5de5\u5382<\/p>\n<\/li>\n<li>\n<p>Builder<br \/>\nBuilder<\/p>\n<\/li>\n<li>\n<p>Prototype<br \/>\n\u539f\u578b<\/p>\n<\/li>\n<li>\n<p>Singleton<br \/>\n\u5355\u4f8b<\/p>\n<\/li>\n<li>\n<p>Objectives<br \/>\n\u76ee\u6807<\/p>\n<\/li>\n<\/ul>\n<p>By the end of this chapter, you will be familiar with creational design patterns and be able to understand their differences. It is also expected that by using the tips provided in this chapter, you can use each creational design pattern in its proper place.<\/p>\n<p>\u5728\u672c\u7ae0\u7ed3\u675f\u65f6\uff0c\u60a8\u5c06\u719f\u6089\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f\u5e76\u80fd\u591f\u7406\u89e3\u5b83\u4eec\u7684\u5dee\u5f02\u3002\u6b64\u5916\uff0c\u901a\u8fc7\u4f7f\u7528\u672c\u7ae0\u4e2d\u63d0\u4f9b\u7684\u63d0\u793a\uff0c\u60a8\u53ef\u4ee5\u5728\u9002\u5f53\u7684\u4f4d\u7f6e\u4f7f\u7528\u6bcf\u4e2a\u521b\u5efa\u6027\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<h2>Creational design pattern<\/h2>\n<h2>\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<\/h2>\n<p>Using creational design patterns, you can understand which object was made by whom, how, and when. In the category of creational design patterns in GoF, five design patterns have been introduced, which are:<\/p>\n<p>\u4f7f\u7528\u521b\u5efa\u6027\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u60a8\u53ef\u4ee5\u4e86\u89e3\u54ea\u4e2a\u5bf9\u8c61\u662f\u7531\u8c01\u3001\u5982\u4f55\u4ee5\u53ca\u4f55\u65f6\u5236\u9020\u7684\u3002\u5728 GoF \u7684\u521b\u5efa\u6027\u8bbe\u8ba1\u6a21\u5f0f\u7c7b\u522b\u4e2d\uff0c\u5f15\u5165\u4e86\u4e94\u79cd\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5b83\u4eec\u662f\uff1a<\/p>\n<ul>\n<li>\n<p>Factory method: Tries to select a class from several existing classes and create an object.<br \/>\nFactory method\uff1a\u5c1d\u8bd5\u4ece\u591a\u4e2a\u73b0\u6709\u7c7b\u4e2d\u9009\u62e9\u4e00\u4e2a\u7c7b\u5e76\u521b\u5efa\u4e00\u4e2a\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>Abstract factory: Tries to create objects from classes of the same family.<br \/>\n\u62bd\u8c61\u5de5\u5382\uff1a\u5c1d\u8bd5\u4ece\u540c\u4e00\u7cfb\u5217\u7684\u7c7b\u521b\u5efa\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>Builder: Tries to separate the object\u2019s construction from its presentation.<br \/>\n\u751f\u6210\u5668\uff1a\u5c1d\u8bd5\u5c06\u5bf9\u8c61\u7684\u6784\u9020\u4e0e\u5176\u8868\u793a\u5206\u5f00\u3002<\/p>\n<\/li>\n<li>\n<p>Prototype: Tries to make a copy of an existing object.<br \/>\n\u539f\u578b\uff1a\u5c1d\u8bd5\u521b\u5efa\u73b0\u6709\u5bf9\u8c61\u7684\u526f\u672c\u3002<\/p>\n<\/li>\n<li>\n<p>Singleton: Tries to have only one object of the class.<br \/>\nSingleton\uff1a\u5c1d\u8bd5\u53ea\u5177\u6709\u7c7b\u7684\u4e00\u4e2a\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<\/ul>\n<p>These five design patterns can be used interchangeably and can be complementary in some situations. For example, the prototype and abstract factory design patterns may be useful in some situations. Or the singleton pattern may be used in the prototype implementation to make the prototype implementation more complete.<\/p>\n<p>\u8fd9\u4e94\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u53ef\u4ee5\u4e92\u6362\u4f7f\u7528\uff0c\u5e76\u4e14\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u53ef\u4ee5\u4e92\u8865\u3002\u4f8b\u5982\uff0c\u539f\u578b\u548c\u62bd\u8c61\u5de5\u5382\u8bbe\u8ba1\u6a21\u5f0f\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u53ef\u80fd\u5f88\u6709\u7528\u3002\u6216\u8005\u53ef\u4ee5\u5728 prototype \u5b9e\u73b0\u4e2d\u4f7f\u7528 singleton \u6a21\u5f0f\uff0c\u4ee5\u4f7f prototype \u5b9e\u73b0\u66f4\u52a0\u5b8c\u6574\u3002<\/p>\n<p>Usually, the creational design patterns can be used for the following conditions:<br \/>\n\u901a\u5e38\uff0c\u521b\u5efa\u6027\u8bbe\u8ba1\u6a21\u5f0f\u53ef\u7528\u4e8e\u4ee5\u4e0b\u6761\u4ef6\uff1a<\/p>\n<ul>\n<li>\n<p>When the system needs to be independent of how the objects are made<br \/>\n\u5f53\u7cfb\u7edf\u9700\u8981\u72ec\u7acb\u4e8e\u5bf9\u8c61\u7684\u521b\u5efa\u65b9\u5f0f\u65f6 <\/p>\n<\/li>\n<li>\n<p>When a set of objects are to be used together<br \/>\n\u5f53\u4e00\u7ec4\u5bf9\u8c61\u4e00\u8d77\u4f7f\u7528\u65f6<\/p>\n<\/li>\n<li>\n<p>When there is a need to hide the class implementation from the user's view<br \/>\n\u5f53\u9700\u8981\u4ece\u7528\u6237\u89c6\u56fe\u4e2d\u9690\u85cf\u7c7b\u5b9e\u73b0\u65f6<\/p>\n<\/li>\n<li>\n<p>When there is a need for different presentations of a complex object.<br \/>\n\u5f53\u9700\u8981\u5bf9\u590d\u6742\u5bf9\u8c61\u8fdb\u884c\u4e0d\u540c\u7684\u8868\u793a\u65f6\u3002<\/p>\n<\/li>\n<li>\n<p>Sampling should be clear at the time of execution.<br \/>\n\u5728\u6267\u884c\u65f6\u5e94\u660e\u786e\u62bd\u6837\u3002<\/p>\n<\/li>\n<li>\n<p>When only one object is required to be provided to the user.<br \/>\n\u5f53\u53ea\u9700\u8981\u5411\u7528\u6237\u63d0\u4f9b\u4e00\u4e2a\u5bf9\u8c61\u65f6\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Apart from the five GoF patterns, other patterns are related to the creation of objects, such as:<\/p>\n<p>\u9664\u4e86\u4e94\u79cd GoF \u6a21\u5f0f\u5916\uff0c\u5176\u4ed6\u6a21\u5f0f\u4e0e\u5bf9\u8c61\u7684\u521b\u5efa\u6709\u5173\uff0c\u4f8b\u5982\uff1a<\/p>\n<ul>\n<li>\n<p>Dependency injection pattern: Instead of creating an object, the class receives the required object through the Injector.<br \/>\n\u4f9d\u8d56\u6ce8\u5165\u6a21\u5f0f\uff1a\u8be5\u7c7b\u4e0d\u662f\u521b\u5efa\u5bf9\u8c61\uff0c\u800c\u662f\u901a\u8fc7 Injector \u63a5\u6536\u6240\u9700\u7684\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>Object pooling pattern: It prevents the object from being destroyed and recreated and reuses the existing objects in the recovery method.<br \/>\n\u5bf9\u8c61\u6c60\u6a21\u5f0f\uff1a\u5b83\u53ef\u4ee5\u9632\u6b62\u5bf9\u8c61\u88ab\u9500\u6bc1\u548c\u91cd\u65b0\u521b\u5efa\uff0c\u5e76\u5728\u6062\u590d\u65b9\u6cd5\u4e2d\u91cd\u7528\u73b0\u6709\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>Lazy initialization pattern: Delays the creation of the object until it is used.<br \/>\n\u5ef6\u8fdf\u521d\u59cb\u5316\u6a21\u5f0f\uff1a\u5ef6\u8fdf\u5bf9\u8c61\u7684\u521b\u5efa\uff0c\u76f4\u5230\u4f7f\u7528\u5b83\u3002<\/p>\n<\/li>\n<\/ul>\n<h2>Factory method<\/h2>\n<h2>\u5de5\u5382\u65b9\u6cd5<\/h2>\n<p>This section introduces and analyzes the factory method design pattern according to the structure presented in the GoF design patterns section in Chapter 1, Introduction to Design Patterns.<\/p>\n<p>\u672c\u8282\u6839\u636e\u7b2c 1 \u7ae0 \u8bbe\u8ba1\u6a21\u5f0f\u7b80\u4ecb\u7684 GoF \u8bbe\u8ba1\u6a21\u5f0f\u90e8\u5206\u4e2d\u4ecb\u7ecd\u7684\u7ed3\u6784\u4ecb\u7ecd\u548c\u5206\u6790\u5de5\u5382\u65b9\u6cd5\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<p>Name:\u540d\u5b57<br \/>\nFactory method\u5de5\u5382\u65b9\u6cd5<\/p>\n<p>Classification:\u5206\u7c7b<br \/>\nCreational design patterns\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<\/p>\n<p>Also known as:\u4e5f\u79f0\u4e3a<br \/>\nVirtual constructor\u865a\u62df\u6784\u9020\u51fd\u6570<\/p>\n<p>Intent:\u610f\u56fe<br \/>\nThis design pattern tries to delegate the creation of objects to child classes in a parent-child structure.\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u5c1d\u8bd5\u5c06\u5bf9\u8c61\u7684\u521b\u5efa\u59d4\u6258\u7ed9\u7236\u5b50\u7ed3\u6784\u4e2d\u7684\u5b50\u7c7b\u3002<\/p>\n<p>Motivation, Structure, Implementation, and Sample code:<br \/>\n\u52a8\u673a\u3001\u7ed3\u6784\u3001\u5b9e\u73b0\u548c\u793a\u4f8b\u4ee3\u7801\uff1a<\/p>\n<p>Suppose we are building a residential unit and must make a &quot;door&quot;. To make a &quot;door&quot;, we must refer to a &quot;door manufacturer&quot;, but so far, we have no idea what type of door we need (wooden, aluminum, iron, and so on). Secondly, we do not know which manufacturer we should refer to (Wooden or iron door manufacturer, and so on). So, we are facing two abstractions here: &quot;door&quot; and &quot;door manufacturer&quot;:<\/p>\n<p>\u5047\u8bbe\u6211\u4eec\u6b63\u5728\u5efa\u9020\u4e00\u4e2a\u4f4f\u5b85\u5355\u5143\uff0c\u5e76\u4e14\u5fc5\u987b\u5236\u4f5c\u4e00\u6247\u201c\u95e8\u201d\u3002\u8981\u5236\u4f5c\u201c\u95e8\u201d\uff0c\u6211\u4eec\u5fc5\u987b\u53c2\u8003\u201c\u95e8\u5236\u9020\u5546\u201d\uff0c\u4f46\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u4e0d\u77e5\u9053\u6211\u4eec\u9700\u8981\u4ec0\u4e48\u7c7b\u578b\u7684\u95e8\uff08\u6728\u95e8\u3001\u94dd\u95e8\u3001\u94c1\u95e8\u7b49\uff09\u3002\u5176\u6b21\uff0c\u6211\u4eec\u4e0d\u77e5\u9053\u6211\u4eec\u5e94\u8be5\u53c2\u8003\u54ea\u4e2a\u5236\u9020\u5546\uff08\u6728\u95e8\u6216\u94c1\u95e8\u5236\u9020\u5546\uff0c\u7b49\u7b49\uff09\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u9762\u4e34\u4e24\u4e2a\u62bd\u8c61\uff1a\u201cdoor\u201d \u548c \u201cdoor manufacturer\u201d\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0201.png\" alt=\"alt text\" \/><br \/>\nFigure 2.1: Door-Door manufacturer relation<br \/>\n\u56fe 2.1\uff1a \u95e8-\u95e8\u5236\u9020\u5546\u5173\u7cfb<\/p>\n<p>According to Figure 2.1, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.1\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>\npublic abstract class Door\n{\n    public abstract void Design();\n    public abstract void Build();\n    public abstract void Coloring();\n}\n\npublic abstract class DoorManufacturer\n{\n    public Door CreateDoor(){}\n}<\/code><\/pre>\n<p>According to the preceding paragraph, we finally decided to choose a &quot;wooden door&quot; for our unit, so we must go to a &quot;carpenter&quot; to make a &quot;wooden door&quot;. It is clear that &quot;wooden door&quot; is a type of &quot;door&quot; and &quot;carpenter&quot; is a type of &quot;door maker&quot;. So, we have two classes WoodenDoor for &quot;wooden door&quot; and Carpenter for &quot;carpenter&quot;.<\/p>\n<p>\u6839\u636e\u524d\u4e00\u6bb5\uff0c\u6211\u4eec\u6700\u540e\u51b3\u5b9a\u4e3a\u6211\u4eec\u7684\u5355\u4f4d\u9009\u62e9\u4e00\u6247\u201c\u6728\u95e8\u201d\uff0c\u90a3\u4e48\u6211\u4eec\u5fc5\u987b\u53bb\u627e\u4e00\u4e2a\u201c\u6728\u5320\u201d\u6765\u5236\u4f5c\u4e00\u6247\u201c\u6728\u95e8\u201d\u3002\u5f88\u660e\u663e\uff0c\u201c\u6728\u95e8\u201d\u662f\u201c\u95e8\u201d\u7684\u4e00\u79cd\uff0c\u800c\u201c\u6728\u5320\u201d\u662f\u201c\u9020\u95e8\u5e08\u201d\u7684\u4e00\u79cd\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u6709\u4e24\u4e2a\u7c7b WoodenDoor \u7528\u4e8e \u201cwooden door\u201d \u548c \u201ccarpenter\u201d \u7684 Carpenter\u3002<\/p>\n<p>On the other hand, we know that Design, Build, and Coloring behaviors can be defined for doors. We still do not know exactly how these behaviors happen for different types of doors (wooden, iron, and so on). To solve this problem in the WoodenDoor class, we need to implement these behaviors to determine how each behavior happens for a wooden door. A similar mechanism should be implemented for other types of doors, such as iron doors.<\/p>\n<p>\u53e6\u4e00\u65b9\u9762\uff0c\u6211\u4eec\u77e5\u9053\u53ef\u4ee5\u4e3a\u95e8\u5b9a\u4e49 Design\u3001Build \u548c Coloring \u884c\u4e3a\u3002\u6211\u4eec\u4ecd\u7136\u4e0d\u77e5\u9053\u8fd9\u4e9b\u884c\u4e3a\u5bf9\u4e8e\u4e0d\u540c\u7c7b\u578b\u7684\u95e8\uff08\u6728\u5236\u3001\u94c1\u5236\u7b49\uff09\u662f\u5982\u4f55\u53d1\u751f\u7684\u3002\u8981\u5728 WoodenDoor \u7c7b\u4e2d\u89e3\u51b3\u6b64\u95ee\u9898\uff0c\u6211\u4eec\u9700\u8981\u5b9e\u73b0\u8fd9\u4e9b\u884c\u4e3a\u6765\u786e\u5b9a\u6728\u95e8\u7684\u6bcf\u79cd\u884c\u4e3a\u662f\u5982\u4f55\u53d1\u751f\u7684\u3002\u5176\u4ed6\u7c7b\u578b\u7684\u95e8\u4e5f\u5e94\u91c7\u7528\u7c7b\u4f3c\u7684\u673a\u5236\uff0c\u4f8b\u5982\u94c1\u95e8\u3002<\/p>\n<p>We also know that a door manufacturer must be able to make a door. To make a door, he must design, build, and color, but we have yet to learn of a door manufacturer. To solve this problem, we add a method called GetDoor to the DoorManufacturer class and specify that this method is responsible for creating a &quot;door manufacturer&quot; type object. Finally, every door manufacturer (such as a wooden door manufacturer) implements this method according to his\/her requirements and processes. Therefore, through this implementation in the DoorManufacturer class, we find out which manufacturer intends to make the door:<\/p>\n<p>\u6211\u4eec\u4e5f\u77e5\u9053\uff0c\u95e8\u5236\u9020\u5546\u5fc5\u987b\u80fd\u591f\u5236\u9020\u95e8\u3002\u8981\u5236\u9020\u95e8\uff0c\u4ed6\u5fc5\u987b\u8bbe\u8ba1\u3001\u5efa\u9020\u548c\u7740\u8272\uff0c\u4f46\u6211\u4eec\u8fd8\u6ca1\u6709\u4e86\u89e3\u5230\u95e8\u5236\u9020\u5546\u3002\u4e3a\u4e86\u89e3\u51b3\u6b64\u95ee\u9898\uff0c\u6211\u4eec\u5c06\u4e00\u4e2a\u540d\u4e3a GetDoor \u7684\u65b9\u6cd5\u6dfb\u52a0\u5230 DoorManufacturer \u7c7b\u4e2d\uff0c\u5e76\u6307\u5b9a\u6b64\u65b9\u6cd5\u8d1f\u8d23\u521b\u5efa\u201c\u95e8\u5236\u9020\u5546\u201d\u7c7b\u578b\u5bf9\u8c61\u3002\u6700\u540e\uff0c\u6bcf\u4e2a\u95e8\u5236\u9020\u5546\uff08\u4f8b\u5982\u6728\u95e8\u5236\u9020\u5546\uff09\u90fd\u6839\u636e\u4ed6\/\u5979\u7684\u8981\u6c42\u548c\u6d41\u7a0b\u5b9e\u65bd\u8fd9\u79cd\u65b9\u6cd5\u3002\u56e0\u6b64\uff0c\u901a\u8fc7 DoorManufacturer \u7c7b\u4e2d\u7684\u8fd9\u4e2a\u5b9e\u73b0\uff0c\u6211\u4eec\u627e\u51fa\u54ea\u4e2a\u5236\u9020\u5546\u6253\u7b97\u5236\u9020\u95e8\uff1a<\/p>\n<pre><code>public abstract class Door\n{\n    public abstract void Design();\n    public abstract void Build();\n    public abstract void Coloring();\n}\n\npublic class WoodenDoor : Door\n{\n    public override void Design()\n    {\n        Console.WriteLine(&quot;Wooden door design done&quot;);\n    }\n\n    public override void Build()\n    {\n        Console.WriteLine(&quot;Wooden door build done&quot;);\n    }\n\n    public override void Coloring()\n    {\n        Console.WriteLine(&quot;Wooden door coloring done&quot;);\n    }\n}\n\npublic abstract class DoorManufacturer\n{\n    public void CreateDoor()\n    {\n    Door door = this.GetDoor();\n    door.Design();\n    door.Build();\n    door.Coloring();\n    Console.WriteLine(&quot;Your door is ready!&quot;);\n    }\n\n    public abstract Door GetDoor();\n}\n\npublic class Carpenter : DoorManufacturer\n{\n    public override Door GetDoor()\n    {\n        return new WoodenDoor();\n    }\n}<\/code><\/pre>\n<p>Finally, we go to the carpenter to make the door and give the desired dimensions and features and ask them to make the door for us:<br \/>\n\u6700\u540e\uff0c\u6211\u4eec\u53bb\u627e\u6728\u5320\u5236\u4f5c\u95e8\uff0c\u7ed9\u51fa\u6240\u9700\u7684\u5c3a\u5bf8\u548c\u529f\u80fd\uff0c\u5e76\u8981\u6c42\u4ed6\u4eec\u4e3a\u6211\u4eec\u5236\u4f5c\u95e8\u3002<\/p>\n<pre><code>DoorManufacturer manufacturer = new Carpenter();\nmanufacturer.CreateDoor();<\/code><\/pre>\n<p>In the preceding design, if we need to add an iron door manufacturer, it is enough to consider a class for an iron door (Let us call it, IronDoor) which inherits from the Door class, and consider a class for an iron door manufacturer (Let us call it, IronDoorMaker) that inherits from DoorManufacturer. In this way, new doors and manufacturers can be defined without manipulating the previous codes. Finally, we will have the following class diagram for this design pattern:<\/p>\n<p>\u5728\u524d\u9762\u7684\u8bbe\u8ba1\u4e2d\uff0c\u5982\u679c\u6211\u4eec\u9700\u8981\u6dfb\u52a0\u4e00\u4e2a\u94c1\u95e8\u5236\u9020\u5546\uff0c\u90a3\u4e48\u8003\u8651\u4e00\u4e2a\u7ee7\u627f\u81ea Door \u7c7b\u7684\u94c1\u95e8\u7c7b\uff08\u6211\u4eec\u79f0\u4e4b\u4e3a IronDoor\uff09\u5c31\u8db3\u591f\u4e86\uff0c\u5e76\u8003\u8651\u4e00\u4e2a\u7ee7\u627f\u81ea DoorManufacturer \u7684\u94c1\u95e8\u5236\u9020\u5546\u7684\u7c7b\uff08\u6211\u4eec\u79f0\u4e4b\u4e3a IronDoorMaker\uff09\u3002\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\uff0c\u53ef\u4ee5\u5728\u4e0d\u7eb5\u5148\u524d\u4ee3\u7801\u7684\u60c5\u51b5\u4e0b\u5b9a\u4e49\u65b0\u7684\u95e8\u548c\u5236\u9020\u5546\u3002\u6700\u540e\uff0c\u6211\u4eec\u5c06\u4e3a\u8fd9\u4e2a\u8bbe\u8ba1\u6a21\u5f0f\u63d0\u4f9b\u4ee5\u4e0b\u7c7b\u56fe\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0202.png\" alt=\"alt text\" \/><br \/>\nFigure 2.2: Factory Method UML diagram<br \/>\n\u56fe 2.2\uff1a \u5de5\u5382\u65b9\u6cd5 UML \u56fe<\/p>\n<p>Participants:<br \/>\n\u53c2\u4e0e\u8005\uff1a<\/p>\n<ul>\n<li>\n<p>Product: Based on the preceding section, the Door is responsible for defining a template for the objects made by the factory method.<br \/>\nProduct\uff1a\u6839\u636e\u4e0a\u4e00\u8282\uff0cDoor \u8d1f\u8d23\u4e3a\u5de5\u5382\u65b9\u6cd5\u751f\u6210\u7684\u5bf9\u8c61\u5b9a\u4e49\u6a21\u677f\u3002<\/p>\n<\/li>\n<li>\n<p>Concrete product: In the preceding scenario, WoodenDoor and IronDoor are responsible for implementing the template defined by the Product.<br \/>\n\u5177\u4f53\u4ea7\u54c1\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cWoodenDoor \u548c IronDoor \u8d1f\u8d23\u5b9e\u73b0 Product \u5b9a\u4e49\u7684\u6a21\u677f\u3002<\/p>\n<\/li>\n<li>\n<p>Creator: This is also called the factory. In the preceding scenario, the DoorManufacturer is responsible for defining the Factory Method. This method is responsible for creating and returning a product-type object. In the preceding scenario, the GetDoor method is the same as the factory method. It is unnecessary to define this method as an abstract method, and the creator class can also have a default implementation of this method.<br \/>\n\u521b\u5efa\u8005\uff1a\u8fd9\u4e5f\u79f0\u4e3a\u5de5\u5382\u3002\u5728\u524d\u9762\u7684\u65b9\u6848\u4e2d\uff0cDoorManufacturer \u8d1f\u8d23\u5b9a\u4e49 Factory Method\u3002\u8be5\u65b9\u6cd5\u8d1f\u8d23\u521b\u5efa\u5e76\u8fd4\u56de product-type \u5bf9\u8c61\u3002\u5728\u524d\u9762\u7684\u65b9\u6848\u4e2d\uff0cGetDoor \u65b9\u6cd5\u4e0e\u5de5\u5382\u65b9\u6cd5\u76f8\u540c\u3002\u6ca1\u6709\u5fc5\u8981\u5c06\u6b64\u65b9\u6cd5\u5b9a\u4e49\u4e3a\u62bd\u8c61\u65b9\u6cd5\uff0c\u5e76\u4e14 creator \u7c7b\u4e5f\u53ef\u4ee5\u5177\u6709\u6b64\u65b9\u6cd5\u7684\u9ed8\u8ba4\u5b9e\u73b0\u3002<\/p>\n<\/li>\n<li>\n<p>Concrete creator: In the preceding scenario, the Carpenter and IronDoorMaker are responsible for rewriting the factory method to make the appropriate object and provide it to the creator.<br \/>\n\u5177\u4f53\u521b\u5efa\u8005\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cCarpenter \u548c IronDoorMaker \u8d1f\u8d23\u91cd\u5199\u5de5\u5382\u65b9\u6cd5\u4ee5\u751f\u6210\u9002\u5f53\u7684\u5bf9\u8c61\u5e76\u5c06\u5176\u63d0\u4f9b\u7ed9\u521b\u5efa\u8005\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Notes:<br \/>\n\u7b14\u8bb0\uff1a<\/p>\n<ul>\n<li>\n<p>In the given implementation and design (Figure 2.2), we can use the interface instead of the abstract class for the product.<br \/>\n\u5728\u7ed9\u5b9a\u7684\u5b9e\u73b0\u548c\u8bbe\u8ba1\uff08\u56fe 2.2\uff09\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u800c\u4e0d\u662f\u4ea7\u54c1\u7684\u62bd\u8c61\u7c7b\u3002<\/p>\n<\/li>\n<li>\n<p>To reuse the created objects, you can use the object pool.<br \/>\nThis design pattern tries to manage the way objects are made, and this is because the factory method design pattern is included in the category of creational design patterns.<br \/>\n\u8981\u91cd\u7528\u521b\u5efa\u7684\u5bf9\u8c61\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u5bf9\u8c61\u6c60\u3002\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u8bd5\u56fe\u7ba1\u7406\u5bf9\u8c61\u7684\u521b\u5efa\u65b9\u5f0f\uff0c\u8fd9\u662f\u56e0\u4e3a\u5de5\u5382\u65b9\u6cd5\u8bbe\u8ba1\u6a21\u5f0f\u5305\u542b\u5728\u521b\u5efa\u8bbe\u8ba1\u6a21\u5f0f\u7684\u7c7b\u522b\u4e2d\u3002<\/p>\n<\/li>\n<li>\n<p>You can also use the Parametrized Factory Method to implement the Factory Method. In this implementation method, we send the type of object we want to create to the Factory Method through a parameter, and through that, we proceed to create the desired object. Concrete Creators can extend these methods by overriding them by using this implementation method. To implement this procedure, the GetDoor method in the preceding scenario is changed as follows:<br \/>\n\u60a8\u8fd8\u53ef\u4ee5\u4f7f\u7528 Parametrized Factory Method \u6765\u5b9e\u73b0 Factory Method\u3002\u5728\u8fd9\u4e2a\u5b9e\u73b0\u65b9\u6cd5\u4e2d\uff0c\u6211\u4eec\u901a\u8fc7\u53c2\u6570\u5c06\u8981\u521b\u5efa\u7684\u5bf9\u8c61\u7c7b\u578b\u53d1\u9001\u5230 Factory Method\uff0c\u7136\u540e\u901a\u8fc7\u8be5\u53c2\u6570\uff0c\u6211\u4eec\u7ee7\u7eed\u521b\u5efa\u6240\u9700\u7684\u5bf9\u8c61\u3002Concrete Creators \u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528\u6b64\u5b9e\u73b0\u65b9\u6cd5\u8986\u76d6\u8fd9\u4e9b\u65b9\u6cd5\u6765\u6269\u5c55\u8fd9\u4e9b\u65b9\u6cd5\u3002\u4e3a\u4e86\u5b9e\u73b0\u6b64\u8fc7\u7a0b\uff0c\u4e0a\u8ff0\u65b9\u6848\u4e2d\u7684 GetDoor \u65b9\u6cd5\u66f4\u6539\u5982\u4e0b\uff1a<\/p>\n<pre><code>public virtual Door GetDoor(string type)\n{\nswitch (type)\n{\n    case &quot;Wooden&quot;:\n    return new WoodenDoor();\n    case &quot;Iron&quot;:\n    return new IronDoor();\n}\nreturn null;\n}<\/code><\/pre>\n<\/li>\n<\/ul>\n<p>In this case, if we want to add the aluminum door manufacturer, we can cover this new requirement by overriding the following method:<br \/>\n\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u5982\u679c\u6211\u4eec\u60f3\u6dfb\u52a0\u94dd\u95e8\u5236\u9020\u5546\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u8986\u76d6\u4ee5\u4e0b\u65b9\u6cd5\u6765\u6ee1\u8db3\u8fd9\u4e2a\u65b0\u8981\u6c42\uff1a<\/p>\n<pre><code>public class AluminumDoorMaker: DoorManufacturer\n{\n    public override Door GetDoor(string type)\n    {\n    if (type == &quot;Aluminum&quot;)\n    return new AluminumDoor();\n    else\n    return base.GetDoor(type);\n    }\n}<\/code><\/pre>\n<p>C# language supports generics from version 2 onwards. This feature of the C# language, instead of creating many subclasses, you can create a product by simply providing a generic type. Using this feature, you can rewrite the concrete creator section as follows:<br \/>\nC# \u8bed\u8a00\u652f\u6301\u7248\u672c 2 \u53ca\u66f4\u9ad8\u7248\u672c\u7684\u6cdb\u578b\u3002C# \u8bed\u8a00\u7684\u8fd9\u4e00\u529f\u80fd\uff0c\u65e0\u9700\u521b\u5efa\u8bb8\u591a\u5b50\u7c7b\uff0c\u53ea\u9700\u63d0\u4f9b\u6cdb\u578b\u7c7b\u578b\u5373\u53ef\u521b\u5efa\u4ea7\u54c1\u3002\u4f7f\u7528\u6b64\u529f\u80fd\uff0c\u60a8\u53ef\u4ee5\u6309\u5982\u4e0b\u65b9\u5f0f\u91cd\u5199 concrete creator \u90e8\u5206\uff1a<\/p>\n<pre><code>public class StarndardDoorManufacturer&lt;T&gt;: DoorManufacturer\n    where T: Door, new()\n    {\n        public override Door GetDoor()\n        {\n        return new T();\n    }\n\n}<\/code><\/pre>\n<p>Pay attention to the where section. With the help of this section, we can filter the generic types so that only types can be sent that are both Door type and its subset types (where T: Door) and also have a default constructor (where T: new()).<\/p>\n<p>\u6ce8\u610f where \u90e8\u5206\u3002\u5728\u672c\u8282\u7684\u5e2e\u52a9\u4e0b\uff0c\u6211\u4eec\u53ef\u4ee5\u8fc7\u6ee4\u6cdb\u578b\u7c7b\u578b\uff0c\u4ee5\u4fbf\u53ea\u80fd\u53d1\u9001\u65e2\u662f Door \u7c7b\u578b\u53c8\u662f\u5176\u5b50\u96c6\u7c7b\u578b\uff08\u5176\u4e2d T\uff1a Door\uff09\u5e76\u4e14\u8fd8\u5177\u6709\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\uff08\u5176\u4e2d T\uff1a new\uff08\uff09\uff09\u7684\u7c7b\u578b\u3002<\/p>\n<p>Finally, with the applied changes, it can be used as follows:<br \/>\n\u6700\u540e\uff0c\u901a\u8fc7\u5e94\u7528\u7684\u66f4\u6539\uff0c\u53ef\u4ee5\u6309\u5982\u4e0b\u65b9\u5f0f\u4f7f\u7528\uff1a<\/p>\n<pre><code>DoorManufacturer obj = new StarndardDoorManufacturer&lt;WoodenDoor&gt;();\n\nobj.CreateDoor();<\/code><\/pre>\n<p>It is better to use a suitable naming template in design patterns so that the design pattern is understood by the template used. It would have been better in the preceding scenario, instead of using the title DoorManufacturer, titles such as DoorFactory or similar were used.<\/p>\n<p>\u6700\u597d\u5728\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\u4f7f\u7528\u5408\u9002\u7684\u547d\u540d\u6a21\u677f\uff0c\u4ee5\u4fbf\u6240\u4f7f\u7528\u7684\u6a21\u677f\u80fd\u591f\u7406\u89e3\u8bbe\u8ba1\u6a21\u5f0f\u3002\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u6700\u597d\u4e0d\u8981\u4f7f\u7528\u6807\u9898 DoorManufacturer\uff0c\u800c\u662f\u4f7f\u7528 DoorFactory \u6216\u7c7b\u4f3c\u6807\u9898\u3002<\/p>\n<p>You can start the design with the factory method, then mature the design with the Abstract factory, prototype, or builder.<\/p>\n<p>\u60a8\u53ef\u4ee5\u4ece factory \u65b9\u6cd5\u5f00\u59cb\u8bbe\u8ba1\uff0c\u7136\u540e\u4f7f\u7528 Abstract factory\u3001prototype \u6216 builder \u5b8c\u5584\u8bbe\u8ba1\u3002<\/p>\n<p>Consequences: Advantages<br \/>\n\u540e\u679c\uff1a\u4f18\u52bf<\/p>\n<p>A loose connection between the creator and the product increases the ability to maintain and develop the code:<\/p>\n<p>\u521b\u5efa\u8005\u548c\u4ea7\u54c1\u4e4b\u95f4\u7684\u677e\u6563\u8fde\u63a5\u589e\u52a0\u4e86\u7ef4\u62a4\u548c\u5f00\u53d1\u4ee3\u7801\u7684\u80fd\u529b\uff1a<\/p>\n<p>The principle of Single Responsibility Principal (SRP) has been observed. By moving the creation of the object outside the factory method, we made each method responsible for doing only one thing.<br \/>\n\u9075\u5b88\u5355\u4e00\u8d23\u4efb\u59d4\u6258\u4eba \uff08SRP\uff09 \u7684\u539f\u5219\u3002\u901a\u8fc7\u5c06\u5bf9\u8c61\u7684\u521b\u5efa\u79fb\u5230\u5de5\u5382\u65b9\u6cd5\u4e4b\u5916\uff0c\u6211\u4eec\u4f7f\u6bcf\u4e2a\u65b9\u6cd5\u53ea\u8d1f\u8d23\u505a\u4e00\u4ef6\u4e8b\u3002<\/p>\n<p>The principle of Open\/Close Principle (OCP) has been observed. As mentioned in the preceding scenario, new products and creators can be added to the program without manipulating the existing codes.<br \/>\n\u5df2\u9075\u5b88\u5f00\/\u5173\u539f\u5219 \uff08OCP\uff09 \u539f\u5219\u3002\u5982\u524d\u9762\u7684\u573a\u666f\u6240\u8ff0\uff0c\u53ef\u4ee5\u5c06\u65b0\u4ea7\u54c1\u548c\u521b\u4f5c\u8005\u6dfb\u52a0\u5230\u7a0b\u5e8f\u4e2d\uff0c\u800c\u65e0\u9700\u4f5c\u73b0\u6709\u4ee3\u7801\u3002<\/p>\n<p>Consequences: Disadvantages<br \/>\n\u540e\u679c\uff1a\u7f3a\u70b9<\/p>\n<p>If the generic feature is not used, then each concrete product and creator must be defined as a subclass. This structure can become complicated to maintain with the increase in the number of classes.<br \/>\n\u5982\u679c\u672a\u4f7f\u7528\u901a\u7528\u7279\u5f81\uff0c\u5219\u5fc5\u987b\u5c06\u6bcf\u4e2a\u5177\u4f53\u4ea7\u54c1\u548c\u521b\u5efa\u8005\u5b9a\u4e49\u4e3a\u4e00\u4e2a\u5b50\u7c7b\u3002\u968f\u7740\u7c7b\u6570\u91cf\u7684\u589e\u52a0\uff0c\u7ef4\u62a4\u6b64\u7ed3\u6784\u53ef\u80fd\u4f1a\u53d8\u5f97\u590d\u6742\u3002<\/p>\n<p>Applicability:<br \/>\n\u9002\u7528\u6027\uff1a<\/p>\n<ul>\n<li>\n<p>When a class does not know the exact type of objects it should create, and need to delegate this task to its child classes.<br \/>\n\u5f53\u4e00\u4e2a\u7c7b\u4e0d\u77e5\u9053\u5b83\u5e94\u8be5\u521b\u5efa\u7684\u5bf9\u8c61\u7684\u786e\u5207\u7c7b\u578b\uff0c\u5e76\u4e14\u9700\u8981\u5c06\u6b64\u4efb\u52a1\u59d4\u6258\u7ed9\u5176\u5b50\u7c7b\u65f6\u3002<\/p>\n<\/li>\n<li>\n<p>When we are developing a software development framework and providing the ability to add new features to the framework.<br \/>\n\u5f53\u6211\u4eec\u5f00\u53d1\u8f6f\u4ef6\u5f00\u53d1\u6846\u67b6\u5e76\u63d0\u4f9b\u5411\u6846\u67b6\u6dfb\u52a0\u65b0\u529f\u80fd\u7684\u80fd\u529b\u65f6\u3002<\/p>\n<\/li>\n<li>\n<p>When we need to control the number of created objects and reuse created objects as much as possible.<br \/>\n\u5f53\u6211\u4eec\u9700\u8981\u63a7\u5236\u5df2\u521b\u5efa\u5bf9\u8c61\u7684\u6570\u91cf\u5e76\u5c3d\u53ef\u80fd\u591a\u5730\u91cd\u7528\u5df2\u521b\u5efa\u7684\u5bf9\u8c61\u65f6\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Related patterns:<br \/>\n\u76f8\u5173\u6a21\u5f0f\uff1a<\/p>\n<p>Some of the following design patterns are not related to the Factory Method design pattern, but to implement this design pattern, checking the following design patterns will be useful:<br \/>\n\u4ee5\u4e0b\u4e00\u4e9b\u8bbe\u8ba1\u6a21\u5f0f\u4e0e Factory Method \u8bbe\u8ba1\u6a21\u5f0f\u65e0\u5173\uff0c\u4f46\u8981\u5b9e\u73b0\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u68c0\u67e5\u4ee5\u4e0b\u8bbe\u8ba1\u6a21\u5f0f\u5c06\u5f88\u6709\u7528\uff1a<\/p>\n<ul>\n<li>Object pool \u5bf9\u8c61\u6c60<\/li>\n<li>Abstract factory \u62bd\u8c61\u5de5\u5382<\/li>\n<li>Template method \u6a21\u677f\u65b9\u6cd5<\/li>\n<li>Singleton \u5355\u4f8b<\/li>\n<li>Iterator \u8fed\u4ee3\u5668<\/li>\n<\/ul>\n<h2>Abstract factory<\/h2>\n<h2>\u62bd\u8c61\u5de5\u5382<\/h2>\n<p>The abstract factory design pattern is introduced and analyzed in this section, according to the structure presented in the GoF design patterns section in Chapter 1, Introduction to Design Patterns.<br \/>\n\u672c\u8282\u6839\u636e\u7b2c 1 \u7ae0 \u8bbe\u8ba1\u6a21\u5f0f\u7b80\u4ecb\u7684 GoF \u8bbe\u8ba1\u6a21\u5f0f\u90e8\u5206\u4ecb\u7ecd\u7684\u7ed3\u6784\uff0c\u4ecb\u7ecd\u548c\u5206\u6790\u62bd\u8c61\u5de5\u5382\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<p>Name:<br \/>\nAbstract factory<br \/>\n\u62bd\u8c61\u5de5\u5382<br \/>\nClassification:<br \/>\nCreational design patterns<br \/>\n\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<br \/>\nAlso known as:<br \/>\nKit<br \/>\n\u5de5\u5177\u7bb1<br \/>\nIntent:<br \/>\nThis design pattern tries to create a group of related objects through an interface without referring to their class.<br \/>\n\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u5c1d\u8bd5\u901a\u8fc7\u63a5\u53e3\u521b\u5efa\u4e00\u7ec4\u76f8\u5173\u5bf9\u8c61\uff0c\u800c\u4e0d\u5f15\u7528\u5b83\u4eec\u7684\u7c7b\u3002<\/p>\n<p>Motivation, Structure, Implementation, and Sample code:<br \/>\n\u52a8\u673a\u3001\u7ed3\u6784\u3001\u5b9e\u73b0\u548c\u793a\u4f8b\u4ee3\u7801\uff1a<br \/>\nWe have several car factories in the country that produce cars. The cars produced by these factories are divided into two categories: gasoline and diesel cars. So far, we are facing two types of abstractions in the scenario. The first abstraction is related to the car manufacturing plant, and the second is related to the type of car. So far in the scenario, we are facing the following class diagram:<br \/>\n\u6211\u4eec\u5728\u8be5\u56fd\u6709\u51e0\u5bb6\u751f\u4ea7\u6c7d\u8f66\u7684\u6c7d\u8f66\u5de5\u5382\u3002\u8fd9\u4e9b\u5de5\u5382\u751f\u4ea7\u7684\u6c7d\u8f66\u5206\u4e3a\u6c7d\u6cb9\u8f66\u548c\u67f4\u6cb9\u8f66\u4e24\u5927\u7c7b\u3002\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u5728\u573a\u666f\u4e2d\u9762\u4e34\u4e24\u79cd\u7c7b\u578b\u7684\u62bd\u8c61\u3002\u7b2c\u4e00\u4e2a\u62bd\u8c61\u4e0e\u6c7d\u8f66\u5236\u9020\u5382\u6709\u5173\uff0c\u7b2c\u4e8c\u4e2a\u62bd\u8c61\u4e0e\u6c7d\u8f66\u7c7b\u578b\u6709\u5173\u3002\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u5728\u8be5\u65b9\u6848\u4e2d\uff0c\u6211\u4eec\u9762\u5bf9\u7684\u662f\u4ee5\u4e0b\u7c7b\u56fe\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0203.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 2.3: Car-Car factory initial relation<br \/>\n\u56fe 2.3\uff1a \u6c7d\u8f66-\u6c7d\u8f66\u5de5\u5382\u7684\u521d\u59cb\u5173\u7cfb<\/p>\n<p>According to Figure 2.3, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.3\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public abstract class CarFactory\n{\n    public abstract PetrolCar CreatePetrolCar();\n    public abstract DieselCar CreateDieselCar();\n}\n\npublic abstract class PetrolCar\n{\n    public abstract void AssembleSeats();\n}\n\npublic abstract class DieselCar\n{\n    public abstract void AssembleDieselEngine();\n}\n<\/code><\/pre>\n<p>According to the class (Figure 2.3 and the preceding code), we must bring classes that use these abstractions to complete the design. For example, the CreatePetrolCar method is in the CarFactory abstract class, but it is unclear how this method is implemented. Logically, it is also true because we still need to know which car manufacturer we are talking about. When it is clear which car manufacturer we are talking about, we can determine how CreatePetrolCar should be implemented. According to the presented scenario, we assume that we have two automobile factories in the country named IranKhodro and Saipa. These factories should be able to produce their own gasoline and diesel products. With this explanation, the preceding design changes as the following:<\/p>\n<p>\u6839\u636e\u7c7b\uff08\u56fe 2.3 \u548c\u524d\u9762\u7684\u4ee3\u7801\uff09\uff0c\u6211\u4eec\u5fc5\u987b\u5f15\u5165\u4f7f\u7528\u8fd9\u4e9b\u62bd\u8c61\u7684\u7c7b\u6765\u5b8c\u6210\u8bbe\u8ba1\u3002\u4f8b\u5982\uff0cCreatePetrolCar \u65b9\u6cd5\u4f4d\u4e8e CarFactory \u62bd\u8c61\u7c7b\u4e2d\uff0c\u4f46\u5c1a\u4e0d\u6e05\u695a\u6b64\u65b9\u6cd5\u662f\u5982\u4f55\u5b9e\u73b0\u7684\u3002\u4ece\u903b\u8f91\u4e0a\u8bb2\uff0c\u8fd9\u4e5f\u662f\u6b63\u786e\u7684\uff0c\u56e0\u4e3a\u6211\u4eec\u4ecd\u7136\u9700\u8981\u77e5\u9053\u6211\u4eec\u6b63\u5728\u8c08\u8bba\u7684\u662f\u54ea\u4e2a\u6c7d\u8f66\u5236\u9020\u5546\u3002\u5f53\u6e05\u695a\u6211\u4eec\u8c08\u8bba\u7684\u662f\u54ea\u4e2a\u6c7d\u8f66\u5236\u9020\u5546\u65f6\uff0c\u6211\u4eec\u53ef\u4ee5\u786e\u5b9a\u5e94\u8be5\u5982\u4f55\u5b9e\u65bd CreatePetrolCar\u3002\u6839\u636e\u6240\u5448\u73b0\u7684\u60c5\u666f\uff0c\u6211\u4eec\u5047\u8bbe\u6211\u4eec\u5728\u8be5\u56fd\u6709\u4e24\u5bb6\u540d\u4e3a IranKhodro \u548c Saipa \u7684\u6c7d\u8f66\u5de5\u5382\u3002\u8fd9\u4e9b\u5de5\u5382\u5e94\u8be5\u80fd\u591f\u751f\u4ea7\u81ea\u5df1\u7684\u6c7d\u6cb9\u548c\u67f4\u6cb9\u4ea7\u54c1\u3002\u901a\u8fc7\u6b64\u8bf4\u660e\uff0c\u524d\u9762\u7684\u8bbe\u8ba1\u5c06\u66f4\u6539\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0204.png\" alt=\"alt text\" \/><br \/>\nFigure 2.4: IranKhodro-Saipa factories relations to CarFactory<br \/>\n\u56fe 2.4\uff1aIranKhodro-Saipa \u5de5\u5382\u4e0e CarFactory \u7684\u5173\u7cfb<\/p>\n<p>According to Figure 2.4, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.4\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public abstract class CarFactory {\n    public abstract PetrolCar CreatePetrolCar();\n    public abstract DieselCar CreateDieselCar();\n}\n\npublic class IranKhodro : CarFactory\n{\n    public override DieselCar CreateDieselCar()=&gt; throw NotImplementedException();\n    public override PetrolCar CreatePetrolCar() =&gt;throw NotImplementedException();\n}\n\npublic class Saipa : CarFactory\n{\n    public override DieselCar CreateDieselCar() =&gt;throw NotImplementedException();\n    public override PetrolCar CreatePetrolCar() =&gt;throw NotImplementedException();\n}\n\npublic abstract class PetrolCar\n{\n    public abstract void AssembleSeats();\n}\n\npublic abstract class DieselCar\n{\n    public abstract void AssembleDieselEngine();\n}<\/code><\/pre>\n<p>So far, it has been found that car factories are making gasoline and diesel cars. We accepted that Iran Khodro and Saipa are car factories, and they produce gasoline and diesel cars. Now the question remains unanswered here: which diesel car does the Iran Khodro or Saipa factory produce? To answer this question, we must first answer which car is gasoline and which is diesel. We can determine which car manufacturer produces gasoline and diesel cars when we answer this question. So, with these conditions, the class diagram changes as the following:<\/p>\n<p>\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u5df2\u7ecf\u53d1\u73b0\u6c7d\u8f66\u5de5\u5382\u6b63\u5728\u751f\u4ea7\u6c7d\u6cb9\u548c\u67f4\u6cb9\u6c7d\u8f66\u3002\u6211\u4eec\u63a5\u53d7\u4e86\u4f0a\u6717 Khodro \u548c Saipa \u662f\u6c7d\u8f66\u5de5\u5382\uff0c\u4ed6\u4eec\u751f\u4ea7\u6c7d\u6cb9\u548c\u67f4\u6cb9\u6c7d\u8f66\u3002\u73b0\u5728\u95ee\u9898\u4ecd\u672a\u5f97\u5230\u89e3\u7b54\uff1a\u4f0a\u6717 Khodro \u6216 Saipa \u5de5\u5382\u751f\u4ea7\u54ea\u79cd\u67f4\u6cb9\u8f66\uff1f\u8981\u56de\u7b54\u8fd9\u4e2a\u95ee\u9898\uff0c\u6211\u4eec\u9996\u5148\u8981\u56de\u7b54\u54ea\u8f86\u8f66\u662f\u6c7d\u6cb9\u8f66\uff0c\u54ea\u8f86\u8f66\u662f\u67f4\u6cb9\u8f66\u3002\u5f53\u6211\u4eec\u56de\u7b54\u8fd9\u4e2a\u95ee\u9898\u65f6\uff0c\u6211\u4eec\u53ef\u4ee5\u786e\u5b9a\u54ea\u4e2a\u6c7d\u8f66\u5236\u9020\u5546\u751f\u4ea7\u6c7d\u6cb9\u548c\u67f4\u6cb9\u6c7d\u8f66\u3002\u56e0\u6b64\uff0c\u5728\u8fd9\u4e9b\u6761\u4ef6\u4e0b\uff0c\u7c7b\u56fe\u5c06\u66f4\u6539\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0205.png\" alt=\"alt text\" \/><br \/>\nFigure 2.5: Factories and cars relations<\/p>\n<p>According to Figure 2.5, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.5\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public abstract class CarFactory\n{\n    public abstract PetrolCar CreatePetrolCar();\n    public abstract DieselCar CreateDieselCar();\n}\n\npublic class IranKhodro : CarFactory\n{\n    public override DieselCar CreateDieselCar() =&gt; new Arena();\n    public override PetrolCar CreatePetrolCar() =&gt; new Peugeot206();\n}\n\npublic class Saipa : CarFactory\n{\n    public override DieselCar CreateDieselCar() =&gt; new Foton();\n    public override PetrolCar CreatePetrolCar() =&gt; new Pride();\n}\n\npublic abstract class PetrolCar\n{\n    public abstract void AssembleSeats();\n}\n\npublic class Pride : PetrolCar\n{\n    public override void AssembleSeats()=&gt;\n    Console.WriteLine(&quot;Pride seats assembled&quot;);\n}\n\npublic class Peugeot206 : PetrolCar\n{\n    public override void AssembleSeats() =&gt;\n    Console.WriteLine(&quot;Peugeot206 seats assembled&quot;);\n}\n\npublic abstract class DieselCar\n{\n    public abstract void AssembleDieselEngine();\n}\n\npublic class Foton : DieselCar\n{\n    public override void AssembleDieselEngine()=&gt;\n    Console.WriteLine(&quot;Foton engine assembled&quot;);\n}\n\npublic class Arena : DieselCar\n{\n    public override void AssembleDieselEngine()=&gt;\n    Console.WriteLine(&quot;Arena engine assembled&quot;);\n}<\/code><\/pre>\n<p>Now, it is clear which car manufacturers produce which cars and how each of these is produced. The design is almost finished, and we only need a user to build the desired car using our defined abstractions. So, with these conditions, the class diagram changes as follows:<\/p>\n<p>\u73b0\u5728\uff0c\u54ea\u4e9b\u6c7d\u8f66\u5236\u9020\u5546\u751f\u4ea7\u54ea\u4e9b\u6c7d\u8f66\u4ee5\u53ca\u6bcf\u8f86\u6c7d\u8f66\u662f\u5982\u4f55\u751f\u4ea7\u7684\uff0c\u8fd9\u4e00\u70b9\u5c31\u5f88\u6e05\u695a\u4e86\u3002\u8bbe\u8ba1\u51e0\u4e4e\u5b8c\u6210\uff0c\u6211\u4eec\u53ea\u9700\u8981\u4e00\u4e2a\u7528\u6237\u4f7f\u7528\u6211\u4eec\u5b9a\u4e49\u7684\u62bd\u8c61\u6765\u6784\u5efa\u6240\u9700\u7684\u6c7d\u8f66\u3002\u56e0\u6b64\uff0c\u5728\u8fd9\u4e9b\u6761\u4ef6\u4e0b\uff0c\u7c7b\u56fe\u5c06\u53d1\u751f\u5982\u4e0b\u53d8\u5316\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0206.png\" alt=\"alt text\" \/><br \/>\nFigure 2.6: Abstract Factory UML diagram<br \/>\n\u56fe 2.6\uff1a \u62bd\u8c61\u5de5\u5382 UML \u56fe<\/p>\n<p>According to Figure 2.6, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.6\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class Client\n{\n    private readonly CarFactory factory;\n    public Client(CarFactory factory) =&gt; this.factory = factory;\n\n    public void CreatePetrolCar()\n    {\n        var petrol = factory.CreatePetrolCar();\n        petrol.AssembleSeats();\n    }\n        public void CreateDieselCar()\n    {\n        var diesel = factory.CreateDieselCar();\n        diesel.AssembleDieselEngine();\n    }\n}<\/code><\/pre>\n<p>As it is clear in the preceding code, the Client receives the car factory in the constructor and creates the cars using CreatePetrolCar and CreateDieselCar methods.<\/p>\n<p>\u5982\u524d\u9762\u7684\u4ee3\u7801\u4e2d\u6240\u793a\uff0c\u5ba2\u6237\u7aef\u5728\u6784\u9020\u51fd\u6570\u4e2d\u63a5\u6536\u6c7d\u8f66\u5de5\u5382\uff0c\u5e76\u4f7f\u7528 CreatePetrolCar \u548c CreateDieselCar \u65b9\u6cd5\u521b\u5efa\u6c7d\u8f66\u3002<\/p>\n<p>Participants:<br \/>\n\u53c2\u4e0e\u8005\uff1a<\/p>\n<ul>\n<li>\n<p>AbstractFactory: In the preceding scenario, the CarFactory has the task of defining a template for tasks whose purpose is to create an AbstractProduct.<br \/>\nAbstractFactory\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cCarFactory \u7684\u4efb\u52a1\u662f\u4e3a\u521b\u5efa AbstractProduct \u7684\u4efb\u52a1\u5b9a\u4e49\u6a21\u677f\u3002<\/p>\n<\/li>\n<li>\n<p>ConcreteFactory: In the preceding scenario, it is IranKhodro and Saipa which has the task of implementing that aim to create a ConcreteProduct.<br \/>\nConcreteFactory\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cIranKhodro \u548c Saipa \u7684\u4efb\u52a1\u662f\u5b9e\u73b0\u521b\u5efa ConcreteProduct \u7684\u76ee\u6807\u3002<\/p>\n<\/li>\n<li>\n<p>AbstractProduct: In the preceding scenario, PetrolCar and DieselCar are responsible for defining the format for all kinds of products.<br \/>\nAbstractProduct\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cPetrolCar \u548c DieselCar \u8d1f\u8d23\u5b9a\u4e49\u5404\u79cd\u4ea7\u54c1\u7684\u683c\u5f0f\u3002<\/p>\n<\/li>\n<li>\n<p>ConcreteProduct: In the preceding scenario, it is Pride, Peugeot206, Arena, and Foton which is responsible for defining the product.<br \/>\nConcreteProduct\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u662f Pride\u3001Peugeot206\u3001Arena \u548c Foton \u8d1f\u8d23\u5b9a\u4e49\u4ea7\u54c1\u3002<\/p>\n<\/li>\n<li>\n<p>Client: This is also called Client, in the preceding scenario, is responsible for using abstractions.<br \/>\nClient\uff1a\u8fd9\u4e5f\u79f0\u4e3a Client\uff0c\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u5b83\u8d1f\u8d23\u4f7f\u7528\u62bd\u8c61\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Notes:<br \/>\n\u7b14\u8bb0\uff1a<\/p>\n<ul>\n<li>\n<p>In the preceding design, instead of the abstract class for CarFactory, PetrolCar, and DieselCar, we can also use interfaces.<br \/>\n\u5728\u524d\u9762\u7684\u8bbe\u8ba1\u4e2d\uff0c\u6211\u4eec\u8fd8\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\uff0c\u800c\u4e0d\u662f CarFactory\u3001PetrolCar \u548c DieselCar \u7684\u62bd\u8c61\u7c7b\u3002<\/p>\n<\/li>\n<li>\n<p>Usually, the classes in this design pattern can be implemented with the factory method or Prototype design pattern.<br \/>\n\u901a\u5e38\uff0c\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\u7684\u7c7b\u53ef\u4ee5\u4f7f\u7528\u5de5\u5382\u65b9\u6cd5\u6216 Prototype \u8bbe\u8ba1\u6a21\u5f0f\u5b9e\u73b0\u3002<\/p>\n<\/li>\n<li>\n<p>If the only purpose is to hide the sampling method, then an abstract factory can be considered an alternative to a Facade.<br \/>\n\u5982\u679c\u552f\u4e00\u76ee\u7684\u662f\u9690\u85cf\u91c7\u6837\u65b9\u6cd5\uff0c\u90a3\u4e48\u62bd\u8c61\u5de5\u5382\u53ef\u4ee5\u88ab\u89c6\u4e3a Facade \u7684\u66ff\u4ee3\u65b9\u6848\u3002<\/p>\n<\/li>\n<li>\n<p>The difference between the builder design pattern and abstract factory is that the Builder design pattern can be used to create complex objects. Also, it is possible to do additional tasks along with the sampling process when using the Builder design pattern. Still, the created sample is returned immediately in the abstract factory design pattern.<br \/>\nBuilder \u8bbe\u8ba1\u6a21\u5f0f\u548c\u62bd\u8c61\u5de5\u5382\u4e4b\u95f4\u7684\u533a\u522b\u5728\u4e8e Builder \u8bbe\u8ba1\u6a21\u5f0f\u53ef\u7528\u4e8e\u521b\u5efa\u590d\u6742\u5bf9\u8c61\u3002\u6b64\u5916\uff0c\u5728\u4f7f\u7528 Builder \u8bbe\u8ba1\u6a21\u5f0f\u65f6\uff0c\u53ef\u4ee5\u5728\u91c7\u6837\u8fc7\u7a0b\u4e2d\u6267\u884c\u5176\u4ed6\u4efb\u52a1\u3002\u5c3d\u7ba1\u5982\u6b64\uff0c\u521b\u5efa\u7684\u793a\u4f8b\u4ecd\u4f1a\u7acb\u5373\u4ee5\u62bd\u8c61\u7684 Factory \u8bbe\u8ba1\u6a21\u5f0f\u8fd4\u56de\u3002<\/p>\n<\/li>\n<li>\n<p>Abstract factory design patterns can also be implemented as Singleton.<br \/>\n\u62bd\u8c61\u5de5\u5382\u8bbe\u8ba1\u6a21\u5f0f\u4e5f\u53ef\u4ee5\u4f5c\u4e3a Singleton \u5b9e\u73b0\u3002<\/p>\n<\/li>\n<li>\n<p>All products of the same family are implemented and integrated into a concrete factory related to that family.<br \/>\n\u540c\u4e00\u7cfb\u5217\u7684\u6240\u6709\u4ea7\u54c1\u90fd\u88ab\u5b9e\u65bd\u5e76\u96c6\u6210\u5230\u4e0e\u8be5\u7cfb\u5217\u76f8\u5173\u7684\u6df7\u51dd\u571f\u5de5\u5382\u4e2d\u3002<\/p>\n<\/li>\n<li>\n<p>In C# language, to implement this design pattern, Generics can be used to design Factory and Product.<br \/>\n\u5728 C# \u8bed\u8a00\u4e2d\uff0c\u4e3a\u4e86\u5b9e\u73b0\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u53ef\u4ee5\u4f7f\u7528\u6cdb\u578b\u6765\u8bbe\u8ba1 Factory \u548c Product\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Consequences: Advantages<br \/>\n\u540e\u679c\uff1a\u4f18\u52bf<\/p>\n<ul>\n<li>\n<p>There is always a guarantee that the products received from the factory are of the same family.<br \/>\n\u59cb\u7ec8\u4fdd\u8bc1\u4ece\u5de5\u5382\u6536\u5230\u7684\u4ea7\u54c1\u5c5e\u4e8e\u540c\u4e00\u7cfb\u5217\u3002<\/p>\n<\/li>\n<li>\n<p>There is a loose connection between the Client and concrete products.<br \/>\n\u5ba2\u6237\u548c\u6df7\u51dd\u571f\u4ea7\u54c1\u4e4b\u95f4\u5b58\u5728\u677e\u6563\u7684\u8054\u7cfb\u3002<\/p>\n<\/li>\n<li>\n<p>The principle of SRP has been observed.<br \/>\n\u5df2\u9075\u5b88 SRP \u7684\u539f\u5219\u3002<\/p>\n<\/li>\n<li>\n<p>The principle of OCP has been observed. New products can be defined without changing the existing codes.<br \/>\nOCP \u7684\u539f\u7406\u5df2\u88ab\u9075\u5b88\u3002\u53ef\u4ee5\u5728\u4e0d\u66f4\u6539\u73b0\u6709\u4ee3\u7801\u7684\u60c5\u51b5\u4e0b\u5b9a\u4e49\u65b0\u4ea7\u54c1\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Consequences: Disadvantages<br \/>\n\u540e\u679c\uff1a\u7f3a\u70b9<\/p>\n<ul>\n<li>\n<p>This structure can become complicated to maintain over time and with the increase in the number of classes.<br \/>\n\u968f\u7740\u65f6\u95f4\u7684\u63a8\u79fb\u548c\u7c7b\u6570\u91cf\u7684\u589e\u52a0\uff0c\u7ef4\u62a4\u8fd9\u79cd\u7ed3\u6784\u53ef\u80fd\u4f1a\u53d8\u5f97\u590d\u6742\u3002<\/p>\n<\/li>\n<li>\n<p>With the addition of a new product, the abstract factory must be changed, which leads to the change of all concrete factories.<br \/>\n\u968f\u7740\u65b0\u4ea7\u54c1\u7684\u52a0\u5165\uff0c\u62bd\u8c61\u5de5\u5382\u5fc5\u987b\u6539\u53d8\uff0c\u8fd9\u5bfc\u81f4\u4e86\u6240\u6709\u5177\u4f53\u5de5\u5382\u7684\u6539\u53d8\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Applicability:<br \/>\n\u9002\u7528\u6027\uff1a<\/p>\n<ul>\n<li>\n<p>When dealing with a family of products and do not want to make the code dependent on concrete products, we can use this pattern.<br \/>\n\u5f53\u5904\u7406\u4e00\u7cfb\u5217\u4ea7\u54c1\u5e76\u4e14\u4e0d\u60f3\u4f7f\u4ee3\u7801\u4f9d\u8d56\u4e8e\u5177\u4f53\u4ea7\u54c1\u65f6\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u79cd\u6a21\u5f0f\u3002<\/p>\n<\/li>\n<li>\n<p>When faced with a class that consists of a collection of factory methods, the abstract factory pattern can be useful.<br \/>\n\u5f53\u9762\u5bf9\u7531\u5de5\u5382\u65b9\u6cd5\u96c6\u5408\u7ec4\u6210\u7684\u7c7b\u65f6\uff0c\u62bd\u8c61\u5de5\u5382\u6a21\u5f0f\u53ef\u80fd\u5f88\u6709\u7528\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Related patterns:<br \/>\n\u76f8\u5173\u6a21\u5f0f\uff1a<br \/>\nSome of the following design patterns are not related to abstract factory design patterns, but to implement this design pattern, checking the following design patterns will be useful:<br \/>\n\u4ee5\u4e0b\u4e00\u4e9b\u8bbe\u8ba1\u6a21\u5f0f\u4e0e\u62bd\u8c61\u5de5\u5382\u8bbe\u8ba1\u6a21\u5f0f\u65e0\u5173\uff0c\u4f46\u8981\u5b9e\u73b0\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u68c0\u67e5\u4ee5\u4e0b\u8bbe\u8ba1\u6a21\u5f0f\u5c06\u5f88\u6709\u7528\uff1a<\/p>\n<ul>\n<li>Prototype \u539f\u578b<\/li>\n<li>Factory method \u5de5\u5382\u65b9\u6cd5<\/li>\n<li>Singleton \u5355\u4f8b<\/li>\n<li>Facade \u7acb\u9762<\/li>\n<li>Builder \u751f\u6210\u5668<\/li>\n<li>Bridge Bridge<\/li>\n<\/ul>\n<h2>Builder<\/h2>\n<h2>\u751f\u6210\u5668\u6a21\u5f0f<\/h2>\n<p>The builder design pattern is introduced and analyzed in this section, according to the structure presented in the GoF design patterns section in Chapter 1, Introduction to Design Pattern.<\/p>\n<p>\u672c\u8282\u6839\u636e\u7b2c 1 \u7ae0 \u8bbe\u8ba1\u6a21\u5f0f\u7b80\u4ecb\u7684 GoF \u8bbe\u8ba1\u6a21\u5f0f\u90e8\u5206\u4ecb\u7ecd\u7684\u7ed3\u6784\uff0c\u4ecb\u7ecd\u548c\u5206\u6790\u4e86\u6784\u5efa\u5668\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<p>Name:<br \/>\nBuilder<br \/>\n\u751f\u6210\u5668\u6a21\u5f0f<br \/>\nClassification:<br \/>\nCreational design patterns<br \/>\n\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<br \/>\nAlso known as:<br \/>\n-<br \/>\nIntent:<br \/>\n\u610f\u56fe\uff1a<br \/>\nThis design pattern tries to create complex objects according to the requirement.<br \/>\n\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u5c1d\u8bd5\u6839\u636e\u8981\u6c42\u521b\u5efa\u590d\u6742\u5bf9\u8c61\u3002<br \/>\nMotivation, Structure, Implementation, and Sample code:<br \/>\n\u52a8\u673a\u3001\u7ed3\u6784\u3001\u5b9e\u73b0\u548c\u793a\u4f8b\u4ee3\u7801\uff1a<br \/>\nSuppose we are building a residential unit. Residential units can have different construction processes according to the use case. A residential unit can be a villa or an apartment, which can be concrete, iron, or prefabricated. To model the residential unit, there are different ways. For example, we can define a parent class for a residential unit and connect different types of residential units to each other using the parent-child relationship. Although this method solves the design problem, in the end, it causes us to face many parent-child relationships that threaten the readability and maintainability of the code.<\/p>\n<p>\u5047\u8bbe\u6211\u4eec\u6b63\u5728\u5efa\u9020\u4e00\u4e2a\u4f4f\u5b85\u5355\u5143\u3002\u6839\u636e\u7528\u4f8b\uff0c\u4f4f\u5b85\u5355\u5143\u53ef\u4ee5\u6709\u4e0d\u540c\u7684\u65bd\u5de5\u6d41\u7a0b\u3002\u4f4f\u5b85\u5355\u5143\u53ef\u4ee5\u662f\u522b\u5885\u6216\u516c\u5bd3\uff0c\u53ef\u4ee5\u662f\u6df7\u51dd\u571f\u3001\u94c1\u6216\u9884\u5236\u7684\u3002\u8981\u5bf9\u4f4f\u5b85\u5355\u5143\u8fdb\u884c\u5efa\u6a21\uff0c\u6709\u591a\u79cd\u65b9\u6cd5\u3002\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u4e3a\u4f4f\u5b85\u5355\u5143\u5b9a\u4e49\u4e00\u4e2a\u7236\u7c7b\uff0c\u5e76\u4f7f\u7528\u7236\u5b50\u5173\u7cfb\u5c06\u4e0d\u540c\u7c7b\u578b\u7684\u4f4f\u5b85\u5355\u5143\u76f8\u4e92\u8fde\u63a5\u3002\u867d\u7136\u8fd9\u79cd\u65b9\u6cd5\u89e3\u51b3\u4e86\u8bbe\u8ba1\u95ee\u9898\uff0c\u4f46\u6700\u7ec8\u8fd8\u662f\u5bfc\u81f4\u6211\u4eec\u9762\u4e34\u5f88\u591a\u7236\u5b50\u5173\u7cfb\uff0c\u5a01\u80c1\u5230\u4ee3\u7801\u7684\u53ef\u8bfb\u6027\u548c\u53ef\u7ef4\u62a4\u6027\u3002<\/p>\n<p>We can use a class to define the residential unit and send all the necessary parameters to define the residential unit through the constructor, in the form of optional parameters, to the class. Although this method solves the design problem, too, it obviously causes the emergence of strange constructors with all the input parameters, which are not given a value when many of them are used.<br \/>\n\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u4e00\u4e2a\u7c7b\u6765\u5b9a\u4e49\u4f4f\u5b85\u5355\u5143\uff0c\u5e76\u901a\u8fc7\u6784\u9020\u51fd\u6570\u4ee5\u53ef\u9009\u53c2\u6570\u7684\u5f62\u5f0f\u5c06\u5b9a\u4e49\u4f4f\u5b85\u5355\u5143\u6240\u9700\u7684\u6240\u6709\u53c2\u6570\u53d1\u9001\u5230\u7c7b\u3002\u867d\u7136\u8fd9\u79cd\u65b9\u6cd5\u4e5f\u89e3\u51b3\u4e86\u8bbe\u8ba1\u95ee\u9898\uff0c\u4f46\u5b83\u663e\u7136\u4f1a\u5bfc\u81f4\u51fa\u73b0\u5177\u6709\u6240\u6709\u8f93\u5165\u53c2\u6570\u7684\u5947\u602a\u6784\u9020\u51fd\u6570\uff0c\u5f53\u4f7f\u7528\u8bb8\u591a\u53c2\u6570\u65f6\uff0c\u8fd9\u4e9b\u53c2\u6570\u6ca1\u6709\u88ab\u8d4b\u4e88\u503c\u3002<\/p>\n<p>For example, we come across the codes like the following:<br \/>\n\u4f8b\u5982\uff0c\u6211\u4eec\u9047\u5230\u4e86\u5982\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>House house1 = new House(p1,p2,null,null,null,null,null,p3,null,null);\n\nHouse house2 = new House(null,null,null,null,null,p4,null,null,null,null);<\/code><\/pre>\n<p>We can put different constructors in the definition of a class, for the residential unit, for different states. Although this method solves the problem, it causes the appearance of telescopic constructors and makes it difficult to maintain the class:<br \/>\n\u6211\u4eec\u53ef\u4ee5\u5728\u7c7b\u7684\u5b9a\u4e49\u4e2d\u4e3a\u4f4f\u5b85\u5355\u5143\u548c\u4e0d\u540c\u7684\u72b6\u6001\u653e\u7f6e\u4e0d\u540c\u7684\u6784\u9020\u51fd\u6570\u3002\u867d\u7136\u8fd9\u79cd\u65b9\u6cd5\u89e3\u51b3\u4e86\u8fd9\u4e2a\u95ee\u9898\uff0c\u4f46\u5b83\u4f1a\u5bfc\u81f4\u4f38\u7f29\u6784\u9020\u5668\u7684\u51fa\u73b0\uff0c\u5e76\u4e14\u5f88\u96be\u7ef4\u62a4\u7c7b\uff1a<\/p>\n<pre><code>public class House{\nPublic House(string p1){}\nPublic House(string p1, string p2){}\nPublic House(string p1, string p2, string p3){}\nPublic House(string p1, string p2, string p3, string p4){}\n\/\/ \u2026\n}<\/code><\/pre>\n<p>The builder design pattern tries to solve these problems. In the preceding example, this design pattern helps to define the stages and steps of building a residential unit so that it is possible to build a residential unit using these stages and steps. For example, separate the wall construction process from the door construction process and present each one separately.<\/p>\n<p>\u6784\u5efa\u5668\u8bbe\u8ba1\u6a21\u5f0f\u5c1d\u8bd5\u89e3\u51b3\u8fd9\u4e9b\u95ee\u9898\u3002\u5728\u524d\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u6709\u52a9\u4e8e\u5b9a\u4e49\u6784\u5efa\u4f4f\u5b85\u5355\u5143\u7684\u9636\u6bb5\u548c\u6b65\u9aa4\uff0c\u4ee5\u4fbf\u53ef\u4ee5\u4f7f\u7528\u8fd9\u4e9b\u9636\u6bb5\u548c\u6b65\u9aa4\u6784\u5efa\u4f4f\u5b85\u5355\u5143\u3002\u4f8b\u5982\uff0c\u5c06\u5899\u6784\u9020\u8fc7\u7a0b\u4e0e\u95e8\u6784\u9020\u8fc7\u7a0b\u5206\u5f00\uff0c\u5e76\u5206\u522b\u5448\u73b0\u6bcf\u4e2a\u8fc7\u7a0b\u3002<\/p>\n<p>To make the matter clear, let us pay attention to another scenario in this regard:<\/p>\n<p>\u4e3a\u4e86\u5f04\u6e05\u695a\u8fd9\u4e2a\u95ee\u9898\uff0c\u8ba9\u6211\u4eec\u6ce8\u610f\u8fd9\u65b9\u9762\u7684\u53e6\u4e00\u79cd\u60c5\u51b5\uff1a<\/p>\n<p>A requirement is raised, and it is requested to provide the ability to make a mobile phone. Based on this requirement, we notice that mobile phones have different models. For example, we consider Samsung and Apple mobile phones. We understand that regardless of the manufacturing company, every mobile phone needs to be manufactured for the screen, body, camera, and so on, and the appropriate operating system is installed on the mobile phone. It is also clear that the manufacturing methods of both Samsung and Apple companies are completely different for each of these parts.<\/p>\n<p>\u63d0\u51fa\u4e86\u4e00\u4e2a\u8981\u6c42\uff0c\u5e76\u8981\u6c42\u63d0\u4f9b\u5236\u4f5c\u624b\u673a\u7684\u80fd\u529b\u3002\u6839\u636e\u8fd9\u4e2a\u8981\u6c42\uff0c\u6211\u4eec\u6ce8\u610f\u5230\u79fb\u52a8\u7535\u8bdd\u7684\u578b\u53f7\u4e0d\u540c\u3002\u4f8b\u5982\uff0c\u6211\u4eec\u8003\u8651\u4e09\u661f\u548c\u82f9\u679c\u624b\u673a\u3002\u6211\u4eec\u660e\u767d\uff0c\u65e0\u8bba\u5236\u9020\u516c\u53f8\u662f\u8c01\uff0c\u6bcf\u90e8\u624b\u673a\u90fd\u9700\u8981\u9488\u5bf9\u5c4f\u5e55\u3001\u673a\u8eab\u3001\u76f8\u673a\u7b49\u8fdb\u884c\u5236\u9020\uff0c\u5e76\u5728\u624b\u673a\u4e0a\u5b89\u88c5\u9002\u5f53\u7684\u4f5c\u7cfb\u7edf\u3002\u540c\u6837\u660e\u663e\u7684\u662f\uff0c\u4e09\u661f\u548c\u82f9\u679c\u516c\u53f8\u7684\u5236\u9020\u65b9\u6cd5\u5bf9\u4e8e\u8fd9\u4e9b\u90e8\u4ef6\u4e2d\u7684\u6bcf\u4e00\u4e2a\u90fd\u5b8c\u5168\u4e0d\u540c\u3002<\/p>\n<p>With these explanations, we are faced with two different elements in the design:<br \/>\n\u901a\u8fc7\u8fd9\u4e9b\u89e3\u91ca\uff0c\u6211\u4eec\u5728\u8bbe\u8ba1\u4e2d\u9762\u4e34\u7740\u4e24\u4e2a\u4e0d\u540c\u7684\u5143\u7d20\uff1a<\/p>\n<ul>\n<li>\n<p>The first element: The product we want to produce<br \/>\n\u7b2c\u4e00\u4e2a\u5143\u7d20\uff1a\u6211\u4eec\u8981\u751f\u4ea7\u7684\u4ea7\u54c1<\/p>\n<\/li>\n<li>\n<p>The second element: The method of making the product<br \/>\n\u7b2c\u4e8c\u4e2a\u5143\u7d20\uff1a\u5236\u4f5c\u4ea7\u54c1\u7684\u65b9\u6cd5<\/p>\n<\/li>\n<\/ul>\n<p>For the first element, we can define two classes for Samsung and Apple, and for the second element, we can use an interface to format the steps of making a mobile phone. With these explanations, we can consider the following class figure:<\/p>\n<p>\u5bf9\u4e8e\u7b2c\u4e00\u4e2a\u5143\u7d20\uff0c\u6211\u4eec\u53ef\u4ee5\u4e3a Samsung \u548c Apple \u5b9a\u4e49\u4e24\u4e2a\u7c7b\uff0c\u5bf9\u4e8e\u7b2c\u4e8c\u4e2a\u5143\u7d20\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u6765\u683c\u5f0f\u5316\u5236\u4f5c\u624b\u673a\u7684\u6b65\u9aa4\u3002\u901a\u8fc7\u8fd9\u4e9b\u89e3\u91ca\uff0c\u6211\u4eec\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u7c7b\u56fe\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0207.png\" alt=\"alt text\" \/><br \/>\nFigure 2.7: Cellphone construction initial relations<br \/>\n\u56fe 2.7\uff1a \u624b\u673a\u6784\u9020\u521d\u59cb\u5173\u7cfb<\/p>\n<p>According to Figure 2.7, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.7\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class CellPhone\n{\n    public string CameraResolution { get; set; }\n    public string MonitorSize { get; set; }\n    public string BodyMaterial { get; set; }\n    public string OSName { get; set; }\n}\n\npublic interface ICellPhoneBuilder\n{\n    public CellPhone Phone { get; }\n    void BuildMonitor();\n    void BuildBody();\n    void BuildCamera();\n    void PrepareOS();\n}\n\npublic class Samsung : ICellPhoneBuilder\n{\n    public CellPhone Phone { get; private set; }\n    public Samsung() =&gt; Phone = new CellPhone();\n    public void BuildBody() =&gt; Phone.BodyMaterial = &quot;Titanium&quot;;\n    public void BuildCamera() =&gt; Phone.CameraResolution = &quot;10 MP&quot;;\n    public void BuildMonitor() =&gt; Phone.MonitorSize = &quot;10 Inch&quot;;\n    public void PrepareOS() =&gt; Phone.OSName = &quot;iOS&quot;;\n}\n\npublic class Apple : ICellPhoneBuilder\n{\n    public CellPhone Phone { get; private set; }\n    public Apple() =&gt; Phone = new CellPhone();\n    public void BuildBody() =&gt; Phone.BodyMaterial = &quot;Aluminum&quot;;\n    public void BuildCamera() =&gt; Phone.CameraResolution = &quot;12 MP&quot;;\n    public void BuildMonitor() =&gt; Phone.MonitorSize = &quot;9.8 Inch&quot;;\n    public void PrepareOS() =&gt; Phone.OSName = &quot;Android 10&quot;;\n}<\/code><\/pre>\n<p>Up to this design point, we have been able to define and implement the necessary steps to make a mobile phone. Now, what is the process of making a mobile phone? How should the defined steps be combined with each other to finally make a mobile phone? To answer these questions, we use the CellPhoneDirector class and define the work process in its format. With these explanations, the class diagram changes as follows:<\/p>\n<p>\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u6211\u4eec\u5df2\u7ecf\u80fd\u591f\u5b9a\u4e49\u548c\u5b9e\u65bd\u5236\u9020\u624b\u673a\u7684\u5fc5\u8981\u6b65\u9aa4\u3002\u90a3\u4e48\uff0c\u5236\u4f5c\u624b\u673a\u7684\u8fc7\u7a0b\u662f\u600e\u6837\u7684\u5462\uff1f\u5b9a\u4e49\u7684\u6b65\u9aa4\u5e94\u8be5\u5982\u4f55\u76f8\u4e92\u7ed3\u5408\uff0c\u6700\u7ec8\u5236\u4f5c\u51fa\u624b\u673a\u5462\uff1f\u4e3a\u4e86\u56de\u7b54\u8fd9\u4e9b\u95ee\u9898\uff0c\u6211\u4eec\u4f7f\u7528 CellPhoneDirector \u7c7b\u5e76\u6309\u5176\u683c\u5f0f\u5b9a\u4e49\u5de5\u4f5c\u6d41\u7a0b\u3002\u901a\u8fc7\u8fd9\u4e9b\u8bf4\u660e\uff0c\u7c7b\u56fe\u5c06\u66f4\u6539\u5982\u4e0b\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0208.png\" alt=\"alt text\" \/><br \/>\nFigure 2.8: Builder design pattern UML diagram<br \/>\n\u56fe 2.8.. Builder \u8bbe\u8ba1\u6a21\u5f0f UML \u56fe<\/p>\n<p>According to Figure 2.8, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.8\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class CellPhoneDirector\n{\nprivate ICellPhoneBuilder builder;\n\npublic CellPhoneDirector(ICellPhoneBuilder builder) =&gt; this.builder = builder;\n\npublic CellPhone Construct()\n{\n    builder.BuildBody();\n    builder.BuildMonitor();\n    builder.BuildCamera();\n    builder.PrepareOS();\n    return builder.Phone;\n}\n\n}<\/code><\/pre>\n<p>According to the preceding code, it is clear that to build a mobile phone (Construct), its body should be built first (BuildBody), then the screen (BuildMonitor), and then the camera should be built (BuildCamera), and finally, the operating system should be prepared (PrepareOS). With these explanations, the design is finished, and to use this structure, you can use the following code:<\/p>\n<p>\u6839\u636e\u524d\u9762\u7684\u4ee3\u7801\uff0c\u5f88\u663e\u7136\uff0c\u8981\u6784\u5efa\u4e00\u90e8\u624b\u673a\uff08Construct\uff09\uff0c\u9996\u5148\u8981\u6784\u5efa\u5b83\u7684\u673a\u8eab\uff08BuildBody\uff09\uff0c\u7136\u540e\u6784\u5efa\u5c4f\u5e55\uff08BuildMonitor\uff09\uff0c\u7136\u540e\u6784\u5efa\u6444\u50cf\u5934\uff08BuildCamera\uff09\uff0c\u6700\u540e\u51c6\u5907\u4f5c\u7cfb\u7edf\uff08PrepareOS\uff09\u3002\u901a\u8fc7\u8fd9\u4e9b\u8bf4\u660e\uff0c\u8bbe\u8ba1\u5c31\u5b8c\u6210\u4e86\uff0c\u8981\u4f7f\u7528\u6b64\u7ed3\u6784\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>CellPhoneDirector director = new CellPhoneDirector(new Samsung());\n\nvar phone = director.Construct();\nConsole.WriteLine($&quot;\n    Body: {phone.BodyMaterial},\n    Camera: {phone.CameraResolution},\n    Monitor: {phone.MonitorSize},\n    OS: {phone.OSName}&quot;\n);\n<\/code><\/pre>\n<p>Participants:<br \/>\n\u53c2\u4e0e\u8005\uff1a<\/p>\n<ul>\n<li>\n<p>Builder: In the preceding scenario, it is ICellPhoneBuilder, which is responsible for defining the format of the steps to build an object. In other words, it has the task of determining what stages and steps should be defined to build an object.<br \/>\nBuilder\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u5b83\u662f ICellPhoneBuilder\uff0c\u5b83\u8d1f\u8d23\u5b9a\u4e49\u6784\u5efa\u5bf9\u8c61\u7684\u6b65\u9aa4\u7684\u683c\u5f0f\u3002\u6362\u53e5\u8bdd\u8bf4\uff0c\u5b83\u7684\u4efb\u52a1\u662f\u786e\u5b9a\u5e94\u8be5\u5b9a\u4e49\u54ea\u4e9b\u9636\u6bb5\u548c\u6b65\u9aa4\u6765\u6784\u5efa\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>ConcreteBuilder: In the preceding scenario, it is Apple and Samsung that are responsible for implementing the steps announced by the builder and specifying how each step should be implemented.<br \/>\nConcreteBuilder\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cApple \u548c Samsung \u8d1f\u8d23\u5b9e\u65bd\u751f\u6210\u5668\u5ba3\u5e03\u7684\u6b65\u9aa4\uff0c\u5e76\u6307\u5b9a\u6bcf\u4e2a\u6b65\u9aa4\u7684\u5b9e\u65bd\u65b9\u5f0f\u3002<\/p>\n<\/li>\n<li>\n<p>Director: In the preceding scenario, it is CellPhoneDirector, which is responsible for implementing the object creation process. During the implementation of this process, the director uses the steps declared by the builder and produces the object.<br \/>\nDirector\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u662f CellPhoneDirector\uff0c\u5b83\u8d1f\u8d23\u5b9e\u73b0\u5bf9\u8c61\u521b\u5efa\u8fc7\u7a0b\u3002\u5728\u6b64\u8fc7\u7a0b\u7684\u5b9e\u65bd\u8fc7\u7a0b\u4e2d\uff0cdirector \u4f7f\u7528\u751f\u6210\u5668\u58f0\u660e\u7684\u6b65\u9aa4\u5e76\u751f\u6210\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>Product: In the preceding scenario, it is the CellPhone that is responsible for defining the complex object that we are trying to build. In fact, the product is built by the Director within ConceretBuilders through the steps defined in the Builder.<br \/>\nProduct\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cCellPhone \u8d1f\u8d23\u5b9a\u4e49\u6211\u4eec\u5c1d\u8bd5\u6784\u5efa\u7684\u590d\u6742\u5bf9\u8c61\u3002\u4e8b\u5b9e\u4e0a\uff0c\u8be5\u4ea7\u54c1\u662f\u7531 ConceretBuilders \u4e2d\u7684 Director \u901a\u8fc7 Builder \u4e2d\u5b9a\u4e49\u7684\u6b65\u9aa4\u6784\u5efa\u7684\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Notes:<br \/>\n\u7b14\u8bb0\uff1a<\/p>\n<ul>\n<li>\n<p>An abstract class can also be used to define Builder.<br \/>\n\u62bd\u8c61\u7c7b\u4e5f\u53ef\u7528\u4e8e\u5b9a\u4e49 Builder\u3002<\/p>\n<\/li>\n<li>\n<p>Using this design pattern, the details of the object construction are hidden from the user's view. If we need to create an object differently, all we need to do is define a new builder.<br \/>\n\u4f7f\u7528\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5bf9\u8c61\u6784\u9020\u7684\u7ec6\u8282\u5bf9\u7528\u6237\u6765\u8bf4\u662f\u9690\u85cf\u7684\u3002\u5982\u679c\u6211\u4eec\u9700\u8981\u4ee5\u4e0d\u540c\u7684\u65b9\u5f0f\u521b\u5efa\u5bf9\u8c61\uff0c\u6211\u4eec\u9700\u8981\u505a\u7684\u5c31\u662f\u5b9a\u4e49\u4e00\u4e2a\u65b0\u7684\u6784\u5efa\u5668\u3002<\/p>\n<\/li>\n<li>\n<p>Using this design pattern, and the director's use, there is more control over the object creation process.The Builder design pattern can also be implemented as a Singleton.<br \/>\n\u4f7f\u7528\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u4ee5\u53ca director \u7684\u4f7f\u7528\uff0c\u53ef\u4ee5\u66f4\u597d\u5730\u63a7\u5236\u5bf9\u8c61\u521b\u5efa\u8fc7\u7a0b\u3002Builder \u8bbe\u8ba1\u6a21\u5f0f\u4e5f\u53ef\u4ee5\u4f5c\u4e3a Singleton \u5b9e\u73b0\u3002<\/p>\n<\/li>\n<li>\n<p>Builder and bridge design patterns can be combined. In this case, the director plays the role of abstraction, and various builders play the role of implementation.<br \/>\nBuilder \u548c Bridge \u8bbe\u8ba1\u6a21\u5f0f\u53ef\u4ee5\u7ec4\u5408\u4f7f\u7528\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0cdirector \u626e\u6f14\u62bd\u8c61\u7684\u89d2\u8272\uff0c\u800c\u5404\u79cd builder \u626e\u6f14 implementation \u7684\u89d2\u8272\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Consequences: Advantages<br \/>\n\u540e\u679c\uff1a\u4f18\u52bf<\/p>\n<ul>\n<li>\n<p>The step-by-step construction of the object allows for better control over the construction process.<br \/>\n\u5bf9\u8c61\u7684\u9010\u6b65\u6784\u9020\u53ef\u4ee5\u66f4\u597d\u5730\u63a7\u5236\u6784\u9020\u8fc7\u7a0b\u3002<\/p>\n<\/li>\n<li>\n<p>Single Responsibility Principle (SRP) is met. The code related to the construction of a complex object is separated from the business logic.<br \/>\n\u6ee1\u8db3\u5355\u4e00\u8d23\u4efb\u539f\u5219 \uff08SRP\uff09\u3002\u4e0e\u590d\u6742\u5bf9\u8c61\u6784\u9020\u76f8\u5173\u7684\u4ee3\u7801\u4e0e\u4e1a\u52a1\u903b\u8f91\u5206\u79bb\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Consequences: Disadvantages<br \/>\n\u540e\u679c\uff1a\u7f3a\u70b9<\/p>\n<ul>\n<li>With the increase in the number of concrete builders, the complexity of the code increases due to the increase in the volume of coding.<br \/>\n\u968f\u7740\u6df7\u51dd\u571f\u6784\u5efa\u5668\u6570\u91cf\u7684\u589e\u52a0\uff0c\u7531\u4e8e\u7f16\u7801\u91cf\u7684\u589e\u52a0\uff0c\u4ee3\u7801\u7684\u590d\u6742\u6027\u4e5f\u968f\u4e4b\u589e\u52a0\u3002<\/li>\n<\/ul>\n<p>Applicability:<br \/>\n\u9002\u7528\u6027\uff1a<\/p>\n<ul>\n<li>\n<p>When we have telescopic constructors in our classes, this design pattern will likely improve the quality of code and design.<br \/>\n\u5f53\u6211\u4eec\u7684\u7c7b\u4e2d\u6709\u4f38\u7f29\u6784\u9020\u5668\u65f6\uff0c\u8fd9\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u53ef\u80fd\u4f1a\u63d0\u9ad8\u4ee3\u7801\u548c\u8bbe\u8ba1\u7684\u8d28\u91cf\u3002<\/p>\n<\/li>\n<li>\n<p>The product manufacturing has the same steps, but the output can be different, then this design pattern will be useful. For example, in the preceding scenario, creating the product in question had the same steps, but the output was different (the Apple company had its own output, and the Samsung company had its own output).<br \/>\n\u4ea7\u54c1\u5236\u9020\u5177\u6709\u76f8\u540c\u7684\u6b65\u9aa4\uff0c\u4f46\u8f93\u51fa\u53ef\u80fd\u4e0d\u540c\uff0c\u90a3\u4e48\u8fd9\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u5c06\u5f88\u6709\u7528\u3002\u4f8b\u5982\uff0c\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u521b\u5efa\u76f8\u5173\u4ea7\u54c1\u7684\u6b65\u9aa4\u76f8\u540c\uff0c\u4f46\u8f93\u51fa\u4e0d\u540c\uff08Apple \u516c\u53f8\u6709\u81ea\u5df1\u7684\u8f93\u51fa\uff0c\u800c Samsung \u516c\u53f8\u6709\u81ea\u5df1\u7684\u8f93\u51fa\uff09\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Related patterns:<br \/>\nSome of the following design patterns are not related to the Builder design pattern, but in order to implement this design pattern, checking the following design patterns will be useful:<br \/>\n\u4ee5\u4e0b\u4e00\u4e9b\u8bbe\u8ba1\u6a21\u5f0f\u4e0e Builder \u8bbe\u8ba1\u6a21\u5f0f\u65e0\u5173\uff0c\u4f46\u4e3a\u4e86\u5b9e\u73b0\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u68c0\u67e5\u4ee5\u4e0b\u8bbe\u8ba1\u6a21\u5f0f\u5c06\u975e\u5e38\u6709\u7528\uff1a<\/p>\n<ul>\n<li>Singleton<\/li>\n<li>Composite<\/li>\n<li>Bridge<\/li>\n<li>Abstract Factory<\/li>\n<\/ul>\n<h2>Prototype<\/h2>\n<h2>\u539f\u578b<\/h2>\n<p>In this section, the prototype design pattern is introduced and analyzed according to the structure presented in the GoF design patterns section in Chapter 1, Introduction to Design Patterns.<br \/>\n\u5728\u672c\u8282\u4e2d\uff0c\u6839\u636e\u7b2c 1 \u7ae0 \u8bbe\u8ba1\u6a21\u5f0f\u7b80\u4ecb\u7684 GoF \u8bbe\u8ba1\u6a21\u5f0f\u90e8\u5206\u4e2d\u4ecb\u7ecd\u7684\u7ed3\u6784\u4ecb\u7ecd\u548c\u5206\u6790\u539f\u578b\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<p>Name:<br \/>\nPrototype<br \/>\n\u539f\u578b<br \/>\nClassification:<br \/>\nCreational design patterns<br \/>\n\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<br \/>\nAlso Known As:<br \/>\n-<br \/>\nIntent:<br \/>\n\u610f\u56fe\uff1a<br \/>\nThis design pattern tries to create objects using a prototype.<br \/>\n\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u5c1d\u8bd5\u4f7f\u7528\u539f\u578b\u521b\u5efa\u5bf9\u8c61\u3002<br \/>\nMotivation, Structure, Implementation, and Sample code:<br \/>\n\u52a8\u673a\u3001\u7ed3\u6784\u3001\u5b9e\u73b0\u548c\u793a\u4f8b\u4ee3\u7801\uff1a<br \/>\nSuppose that we have a clothing factory, and we intend to produce different types of pants. The usual method is that the pants are designed first. Then, a pair of pants is produced as a sample based on this design. Finally, the rest of the pants are mass-produced. Pants that are designed and produced at the beginning are called prototypes. According to this scenario, it is very important to define a method to mass-produce the rest of the pants from the prototype.<br \/>\n\u5047\u8bbe\u6211\u4eec\u6709\u4e00\u5bb6\u670d\u88c5\u5382\uff0c\u6211\u4eec\u6253\u7b97\u751f\u4ea7\u4e0d\u540c\u7c7b\u578b\u7684\u88e4\u5b50\u3002\u901a\u5e38\u7684\u65b9\u6cd5\u662f\u5148\u8bbe\u8ba1\u88e4\u5b50\u3002\u7136\u540e\uff0c\u6839\u636e\u6b64\u8bbe\u8ba1\u751f\u4ea7\u4e00\u6761\u88e4\u5b50\u4f5c\u4e3a\u6837\u54c1\u3002\u6700\u540e\uff0c\u5176\u4f59\u7684\u88e4\u5b50\u90fd\u8fdb\u884c\u4e86\u6279\u91cf\u751f\u4ea7\u3002\u4e00\u5f00\u59cb\u8bbe\u8ba1\u548c\u751f\u4ea7\u7684\u88e4\u5b50\u79f0\u4e3a\u539f\u578b\u3002\u6839\u636e\u8fd9\u4e2a\u573a\u666f\uff0c\u5b9a\u4e49\u4e00\u79cd\u65b9\u6cd5\u6765\u4ece\u539f\u578b\u4e2d\u6279\u91cf\u751f\u4ea7\u5176\u4f59\u88e4\u5b50\u662f\u975e\u5e38\u91cd\u8981\u7684\u3002<\/p>\n<p>There are different types of pants, such as jeans, linen, and cloth pants. The production of each prototype is different from the other. But in the meantime, having a method for mass production of any pants (copying) is common among different types of pants. According to this scenario, we face the following class diagram:<br \/>\n\u6709\u4e0d\u540c\u7c7b\u578b\u7684\u88e4\u5b50\uff0c\u4f8b\u5982\u725b\u4ed4\u88e4\u3001\u4e9a\u9ebb\u5e03\u548c\u5e03\u88e4\u3002\u6bcf\u4e2a\u539f\u578b\u7684\u751f\u4ea7\u90fd\u4e0d\u540c\u3002\u4f46\u4e0e\u6b64\u540c\u65f6\uff0c\u62e5\u6709\u4e00\u79cd\u5927\u89c4\u6a21\u751f\u4ea7\u4efb\u4f55\u88e4\u5b50\uff08\u590d\u5236\uff09\u7684\u65b9\u6cd5\u5728\u4e0d\u540c\u7c7b\u578b\u7684\u88e4\u5b50\u4e2d\u5f88\u5e38\u89c1\u3002\u6839\u636e\u6b64\u65b9\u6848\uff0c\u6211\u4eec\u9762\u5bf9\u4ee5\u4e0b\u7c7b\u56fe\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0209.png\" alt=\"alt text\" \/><br \/>\nFigure 2.9: Pants initial relation<\/p>\n<p>According to Figure 2.9, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.9\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public interface IPant\n{\n    IPant Clone();\n}\n\npublic class FabricPant : IPant\n{\n    public IPant Clone() =&gt; this.MemberwiseClone() as IPant;\n}\n\npublic class CottonPant : IPant\n{\n    public IPant Clone() =&gt; this.MemberwiseClone() as IPant;\n}\n\npublic class JeanPant : IPant\n{\n    public IPant Clone() =&gt; this.MemberwiseClone() as IPant;\n}<\/code><\/pre>\n<p>According to the preceding structure, to copy the pants, the clone method is defined in the IPant interface, and each class copies the object using the MemberwiseClone method.<\/p>\n<p>\u6839\u636e\u524d\u9762\u7684\u7ed3\u6784\uff0c\u8981\u590d\u5236 pants\uff0c\u5728 IPant \u63a5\u53e3\u4e2d\u5b9a\u4e49\u4e86 clone \u65b9\u6cd5\uff0c\u6bcf\u4e2a\u7c7b\u90fd\u4f7f\u7528 MemberwiseClone \u65b9\u6cd5\u590d\u5236\u5bf9\u8c61\u3002<\/p>\n<p>Now that the design is finished, the following structure can be used:<br \/>\n\u73b0\u5728\u8bbe\u8ba1\u5df2\u5b8c\u6210\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u7ed3\u6784\uff1a<\/p>\n<pre><code>IPant jean1 = new JeanPant();\n\nIPant jean2 = jean1.Clone();<\/code><\/pre>\n<p>The point in the preceding code is the method of copying the object. The objects are copied using the shallow method. In shallow copying, value types are copied bit by bit, but in the case of reference types, only the address is copied, and not the object, which causes another object to be affected by changing the value. To prevent this from happening, the deep method should be used to copy objects. Refer to the following figure:<br \/>\n\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u7684\u8981\u70b9\u662f\u590d\u5236\u5bf9\u8c61\u7684\u65b9\u6cd5\u3002\u4f7f\u7528 shallow \u65b9\u6cd5\u590d\u5236\u5bf9\u8c61\u3002\u5728\u6d45\u5c42\u590d\u5236\u4e2d\uff0c\u503c\u7c7b\u578b\u662f\u9010\u4f4d\u590d\u5236\u7684\uff0c\u4f46\u5728\u5f15\u7528\u7c7b\u578b\u7684\u60c5\u51b5\u4e0b\uff0c\u53ea\u590d\u5236\u5730\u5740\uff0c\u800c\u4e0d\u590d\u5236\u5bf9\u8c61\uff0c\u8fd9\u4f1a\u5bfc\u81f4\u53e6\u4e00\u4e2a\u5bf9\u8c61\u53d7\u5230\u66f4\u6539\u503c\u7684\u5f71\u54cd\u3002\u4e3a\u4e86\u9632\u6b62\u8fd9\u79cd\u60c5\u51b5\u53d1\u751f\uff0c\u5e94\u8be5\u4f7f\u7528 deep \u65b9\u6cd5\u6765\u590d\u5236\u5bf9\u8c61\u3002\u53c2\u8003\u4e0b\u56fe\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0210.png\" alt=\"alt text\" \/><br \/>\nFigure 2.10: Shallow Copy<br \/>\n\u56fe 2.10.. \u6d45\u62f7\u8d1d<\/p>\n<p>The preceding figure shows the shallow copy, in which object X1 refers to B1 and object B1 also refers to C1. After copying, a new object named X2 is created, which still refers to B1. Therefore, applying a change in B1 through X1 will cause this change to be felt by object X2 as well:<br \/>\n\u4e0a\u56fe\u663e\u793a\u4e86\u6d45\u62f7\u8d1d\uff0c\u5176\u4e2d\u5bf9\u8c61 X1 \u5f15\u7528 B1\uff0c\u5bf9\u8c61 B1 \u4e5f\u5f15\u7528 C1\u3002\u590d\u5236\u540e\uff0c\u5c06\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a X2 \u7684\u65b0\u5bf9\u8c61\uff0c\u8be5\u5bf9\u8c61\u4ecd\u5f15\u7528 B1\u3002\u56e0\u6b64\uff0c\u5728 B1 \u5230 X1 \u4e2d\u5e94\u7528\u66f4\u6539\u5c06\u5bfc\u81f4\u5bf9\u8c61 X2 \u4e5f\u80fd\u611f\u53d7\u5230\u6b64\u66f4\u6539\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0211.png\" alt=\"alt text\" \/><br \/>\nFigure 2.11: Deep Copy<\/p>\n<p>The preceding figure also shows the copy by deep method, in which after the creation of object X2, new objects B2 and C2 are also created, and X2 refers to new objects B2 and C2. Therefore, applying changes in B1 through X1 will not cause these changes to be felt in object X2.<\/p>\n<p>\u4e0a\u56fe\u8fd8\u663e\u793a\u4e86 deep \u590d\u5236\u65b9\u6cd5\uff0c\u5176\u4e2d\u5728\u521b\u5efa\u5bf9\u8c61 X2 \u4e4b\u540e\uff0c\u8fd8\u4f1a\u521b\u5efa\u65b0\u7684\u5bf9\u8c61 B2 \u548c C2\uff0cX2 \u5f15\u7528\u65b0\u7684\u5bf9\u8c61 B2 \u548c C2\u3002\u56e0\u6b64\uff0c\u5728 B1 \u5230 X1 \u4e2d\u5e94\u7528\u66f4\u6539\u4e0d\u4f1a\u5bfc\u81f4\u5728\u5bf9\u8c61 X2 \u4e2d\u611f\u89c9\u5230\u8fd9\u4e9b\u66f4\u6539\u3002<\/p>\n<p>According to the preceding explanations, and to clarify the differences between the shallow and deep methods, we also define another method called DeepClone. There are different methods to implement deep copy. Here we use the following method. Also, we define a class called Cloth, and we define the characteristics of the fabric through this class. The following code can be considered:<\/p>\n<p>\u6839\u636e\u524d\u9762\u7684\u89e3\u91ca\uff0c\u4e3a\u4e86\u660e\u786e shallow \u548c deep \u65b9\u6cd5\u4e4b\u95f4\u7684\u533a\u522b\uff0c\u6211\u4eec\u8fd8\u5b9a\u4e49\u4e86\u53e6\u4e00\u79cd\u540d\u4e3a DeepClone \u7684\u65b9\u6cd5\u3002\u6709\u591a\u79cd\u65b9\u6cd5\u53ef\u4ee5\u5b9e\u73b0 Deep Copy\u3002\u8fd9\u91cc\u6211\u4eec\u4f7f\u7528\u4ee5\u4e0b\u65b9\u6cd5\u3002\u6b64\u5916\uff0c\u6211\u4eec\u5b9a\u4e49\u4e86\u4e00\u4e2a\u540d\u4e3a Cloth \u7684\u7c7b\uff0c\u6211\u4eec\u901a\u8fc7\u8fd9\u4e2a\u7c7b\u6765\u5b9a\u4e49\u7ec7\u7269\u7684\u7279\u6027\u3002\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class Cloth\n{\n    public string Color { get; set; }\n}\n\npublic interface IPant\n{\n    public int Price { get; set; }\n    public Cloth ClothInfo { get; set; }\n\n    IPant Clone();\n    IPant DeepClone();\n}\n\npublic class JeanPant : IPant\n{\n    public int Price { get; set; }\n    public Cloth ClothInfo { get; set; }\n\n    public IPant Clone() =&gt; this.MemberwiseClone() as IPant;\n\n    public IPant DeepClone()\n    {\n    JeanPant pant = this.MemberwiseClone() as JeanPant;\n    pant.ClothInfo = new Cloth() { Color = this.ClothInfo.Color };\n    return pant;\n    }\n\n    public override string ToString() =&gt;\n    $&quot;Color:{this.ClothInfo.Color}, Price: {this.Price}&quot;;\n}<\/code><\/pre>\n<p>Now, to check the output of each method, we will test the copy methods using the following code. For Shallow copying, we have:<br \/>\n\u73b0\u5728\uff0c\u4e3a\u4e86\u68c0\u67e5\u6bcf\u4e2a\u65b9\u6cd5\u7684\u8f93\u51fa\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u4ee5\u4e0b\u4ee3\u7801\u6d4b\u8bd5 copy \u65b9\u6cd5\u3002\u5bf9\u4e8e\u6d45\u62f7\u8d1d\uff0c\u6211\u4eec\u6709\uff1a<\/p>\n<pre><code>IPant jean1 = new JeanPant()\n{\n    Price = 10000,\n    ClothInfo = new Cloth(){ Color = &quot;Red&quot;}\n};\n\nIPant jean2 = jean1.Clone() ;\/\/Shallow Copy\njean2.Price = 11000;\njean2.ClothInfo.Color = &quot;Geen&quot;;\nConsole.WriteLine($&quot;jean1: {jean1}&quot;);\n\nConsole.WriteLine($&quot;jean2: {jean2}&quot;);<\/code><\/pre>\n<p>By running the preceding code, we get the following output:<br \/>\n\u901a\u8fc7\u8fd0\u884c\u4e0a\u8ff0\u4ee3\u7801\uff0c\u6211\u4eec\u5f97\u5230\u4ee5\u4e0b\u8f93\u51fa\uff1a<\/p>\n<pre><code>jean1: Color: Geen, Price: 10000\njean2: Color: Geen, Price: 11000<\/code><\/pre>\n<p>In this copy method, for reference types, only the reference address is copied; changing the value in ClothInfo through jean2 causes the ClothInfo value in jean1 to change as well.<br \/>\n\u5728\u6b64 copy \u65b9\u6cd5\u4e2d\uff0c\u5bf9\u4e8e\u5f15\u7528\u7c7b\u578b\uff0c\u4ec5\u590d\u5236\u5f15\u7528\u5730\u5740;\u901a\u8fc7 jean2 \u66f4\u6539 ClothInfo \u4e2d\u7684\u503c\u4f1a\u5bfc\u81f4 jean1 \u4e2d\u7684 ClothInfo \u503c\u4e5f\u53d1\u751f\u66f4\u6539\u3002<\/p>\n<p>But if we use DeepClone instead of the clone method in the preceding code, then we will see the following output:<br \/>\n\u4f46\u662f\uff0c\u5982\u679c\u6211\u4eec\u5728\u524d\u9762\u7684\u4ee3\u7801\u4e2d\u4f7f\u7528 DeepClone \u800c\u4e0d\u662f clone \u65b9\u6cd5\uff0c\u90a3\u4e48\u6211\u4eec\u5c06\u770b\u5230\u4ee5\u4e0b\u8f93\u51fa\uff1a<\/p>\n<pre><code>jean1: Color: Red, Price: 10000\njean2: Color: Geen, Price: 11000<\/code><\/pre>\n<p>Now, if we return to the proposed scenario, we can slightly change the design provided for the Prototype design pattern.<br \/>\n\u73b0\u5728\uff0c\u5982\u679c\u6211\u4eec\u8fd4\u56de\u5230\u5efa\u8bae\u7684\u573a\u666f\uff0c\u6211\u4eec\u53ef\u4ee5\u7a0d\u5fae\u66f4\u6539\u4e3a Prototype \u8bbe\u8ba1\u6a21\u5f0f\u63d0\u4f9b\u7684\u8bbe\u8ba1\u3002<\/p>\n<p>In the current design,It is not yet clear how the user can communicate.<br \/>\n\u76ee\u524d\u5c1a\u4e0d\u6e05\u695a\u7528\u6237\u5982\u4f55\u8fdb\u884c\u901a\u4fe1\u3002<\/p>\n<p>Also, in the current design, when the number of prototypes is not a fixed value, and the prototypes can be dynamically created and destroyed, no solution has been provided.<\/p>\n<p>\u6b64\u5916\uff0c\u5728\u5f53\u524d\u8bbe\u8ba1\u4e2d\uff0c\u5f53\u539f\u578b\u7684\u6570\u91cf\u4e0d\u662f\u56fa\u5b9a\u503c\uff0c\u5e76\u4e14\u53ef\u4ee5\u52a8\u6001\u521b\u5efa\u548c\u9500\u6bc1\u539f\u578b\u65f6\uff0c\u6ca1\u6709\u63d0\u4f9b\u4efb\u4f55\u89e3\u51b3\u65b9\u6848\u3002<\/p>\n<p>To answer the first requirement, the user communication to produce objects in the preceding scenario should be through IPant. For the second requirement, another class can be used as Registry, and the user's relationship with the prototype can be promoted through the registry as the following:<br \/>\n\u4e3a\u4e86\u6ee1\u8db3\u7b2c\u4e00\u4e2a\u8981\u6c42\uff0c\u5728\u524d\u9762\u7684\u65b9\u6848\u4e2d\u751f\u6210\u5bf9\u8c61\u7684\u7528\u6237\u901a\u4fe1\u5e94\u901a\u8fc7 IPant \u8fdb\u884c\u3002\u5bf9\u4e8e\u7b2c\u4e8c\u4e2a\u8981\u6c42\uff0c\u53ef\u4ee5\u4f7f\u7528\u53e6\u4e00\u4e2a\u7c7b\u4f5c\u4e3a Registry\uff0c\u5e76\u4e14\u7528\u6237\u4e0e\u539f\u578b\u7684\u5173\u7cfb\u53ef\u4ee5\u901a\u8fc7 Registry \u8fdb\u884c\u63d0\u5347\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0212.png\" alt=\"alt text\" \/><br \/>\nFigure 2.12: Prototype design pattern UML diagram<br \/>\n\u56fe 2.12\uff1a \u539f\u578b\u8bbe\u8ba1\u6a21\u5f0f UML \u56fe<\/p>\n<p>According to Figure 2.12, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.12\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class PantRegistry\n{\n    public PantRegistry() =&gt; Pants = new List&lt;IPant&gt;();\n    public List&lt;IPant&gt; Pants { get; private set; }\n    public void Add(IPant obj) =&gt; Pants.Add(obj);\n    public IPant GetByColor(string color) =&gt;\n        Pants\n        .OrderBy(x =&gt; Guid.NewGuid())\n        .FirstOrDefault(x =&gt; x.ClothInfo.Color == color)\n        .DeepClone();\n\n    public IPant GetByType(Type type) =&gt;\n        Pants\n        .OrderBy(x =&gt; Guid.NewGuid())\n        .FirstOrDefault(x =&gt; x.GetType() == type)\n        .DeepClone();\n\n}\n<\/code><\/pre>\n<p>In the preceding code, a feature called Pants is presented, which has the role of a reservoir, and objects are stored in this reservoir. The Add method is used to store the new object in the repository, and the GetByColor and GetByType methods are used to search the repository and find the desired object and copy it. To use this code, you can do the following:<br \/>\n\u5728\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d\uff0c\u63d0\u51fa\u4e86\u4e00\u4e2a\u540d\u4e3a Pants \u7684\u529f\u80fd\uff0c\u5b83\u5177\u6709 reservoir \u7684\u89d2\u8272\uff0c\u5e76\u4e14\u5bf9\u8c61\u5b58\u50a8\u5728\u6b64 reservoir \u4e2d\u3002Add \u65b9\u6cd5\u7528\u4e8e\u5c06\u65b0\u5bf9\u8c61\u5b58\u50a8\u5728\u5b58\u50a8\u5e93\u4e2d\uff0cGetByColor \u548c GetByType \u65b9\u6cd5\u7528\u4e8e\u641c\u7d22\u5b58\u50a8\u5e93\u5e76\u67e5\u627e\u6240\u9700\u5bf9\u8c61\u5e76\u590d\u5236\u5b83\u3002\u8981\u4f7f\u7528\u6b64\u4ee3\u7801\uff0c\u60a8\u53ef\u4ee5\u6267\u884c\u4ee5\u4e0b\u4f5c\uff1a<\/p>\n<pre><code>IPant jean1 = new JeanPant()\n{\n    Price = 10000,\n    ClothInfo = new Cloth() { Color = &quot;Red&quot; }\n};\n\nIPant cotton1 = new CottonPant()\n{\n    Price = 7000,\n    ClothInfo = new Cloth() { Color = &quot;Red&quot; }\n};\n\nIPant fabric1 = new FabricPant()\n{\n    Price = 12000,\n    ClothInfo = new Cloth() { Color = &quot;Blue&quot; }\n};\n\nPantRegistry registry = new PantRegistry();\nregistry.Add(jean1);\nregistry.Add(cotton1);\nregistry.Add(fabric1);\nConsole.WriteLine($&quot;{jean1}&quot;);\n\n\/\/ Get a pair of jeans\nConsole.WriteLine($&quot;{registry.GetByType(typeof(JeanPant))}&quot;);\n\n\/\/ Get a pair of red pants regardless of the type of pants\nConsole.WriteLine($&quot;{registry.GetByColor(&quot;Red&quot;)}&quot;);<\/code><\/pre>\n<p>As you can see in the preceding code, the objects are added to the repository after being created, searched, and copied through different methods.<\/p>\n<p>\u5982\u524d\u9762\u7684\u4ee3\u7801\u6240\u793a\uff0c\u5bf9\u8c61\u5728\u901a\u8fc7\u4e0d\u540c\u7684\u65b9\u6cd5\u521b\u5efa\u3001\u641c\u7d22\u548c\u590d\u5236\u540e\u4f1a\u6dfb\u52a0\u5230\u5b58\u50a8\u5e93\u4e2d\u3002<\/p>\n<p>Participants:<br \/>\n\u53c2\u4e0e\u8005\uff1a<\/p>\n<ul>\n<li>\n<p>Prototype: In the preceding scenario, it is IPant that is responsible for defining the template for copying the object<br \/>\n\u539f\u578b\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u662f IPant \u8d1f\u8d23\u5b9a\u4e49\u7528\u4e8e\u590d\u5236\u5bf9\u8c61\u7684<\/p>\n<\/li>\n<li>\n<p>Concrete prototype: In the preceding scenario, it is CottonPant, JeanPant, and FabricPant, which is responsible for implementing the provided template for copying the object.<br \/>\n\u6a21\u677f\u5177\u4f53\u539f\u578b\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0c\u662f CottonPant\u3001JeanPant \u548c FabricPant \u8d1f\u8d23\u5b9e\u73b0\u63d0\u4f9b\u7684\u7528\u4e8e\u590d\u5236\u5bf9\u8c61\u7684\u6a21\u677f\u3002<\/p>\n<\/li>\n<li>\n<p>Prototype registry: which is also called Prototype Manager. In the preceding scenario, it is PantRegistry whose task is to facilitate access to objects.<br \/>\nPrototype registry\uff1a\u4e5f\u79f0\u4e3a Prototype Manager\u3002\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cPantRegistry \u7684\u4efb\u52a1\u662f\u4fc3\u8fdb\u5bf9\u5bf9\u8c61\u7684\u8bbf\u95ee\u3002<\/p>\n<\/li>\n<li>\n<p>Client: It is the same user who sends a request to create a new object through Prototype or Prototype Registry.<br \/>\n\u5ba2\u6237\u7aef\uff1a\u901a\u8fc7 Prototype \u6216 Prototype Registry \u53d1\u9001\u521b\u5efa\u65b0\u5bf9\u8c61\u7684\u8bf7\u6c42\u7684\u540c\u4e00\u7528\u6237\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Notes:<\/p>\n<ul>\n<li>\n<p>In .NET, the ICloneable interface can also be used as a prototype.<br \/>\n\u5728 .NET \u4e2d\uff0cICloneable \u63a5\u53e3\u4e5f\u53ef\u4ee5\u7528\u4f5c\u539f\u578b\u3002<\/p>\n<\/li>\n<li>\n<p>Singleton can also be used in the implementation of the prototype design pattern.<br \/>\nSingleton \u4e5f\u53ef\u4ee5\u7528\u4e8e\u539f\u578b\u8bbe\u8ba1\u6a21\u5f0f\u7684\u5b9e\u73b0\u3002<\/p>\n<\/li>\n<li>\n<p>In the command design pattern, if you need to save history, you can use the prototype design pattern.<br \/>\n\u5728\u547d\u4ee4\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\uff0c\u5982\u679c\u9700\u8981\u4fdd\u5b58\u5386\u53f2\u8bb0\u5f55\uff0c\u53ef\u4ee5\u4f7f\u7528 prototype \u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<\/li>\n<li>\n<p>If there is a need to store the state of the object and this object:<br \/>\n\u5982\u679c\u9700\u8981\u5b58\u50a8\u5bf9\u8c61\u548c\u6b64\u5bf9\u8c61\u7684 state\uff1a<\/p>\n<\/li>\n<li>\n<ul>\n<li>It is not a complex object.<br \/>\n\u5b83\u4e0d\u662f\u4e00\u4e2a\u590d\u6742\u5bf9\u8c61\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\n<ul>\n<li>Does not have complex references or can be defined easily.<br \/>\n\u6ca1\u6709\u590d\u6742\u7684\u5f15\u7528\u6216\u53ef\u4ee5\u8f7b\u677e\u5b9a\u4e49\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\n<ul>\n<li>Then the prototype design pattern can be used instead of the memento design pattern.<br \/>\n\u7136\u540e\uff0c\u53ef\u4ee5\u4f7f\u7528 prototype \u8bbe\u8ba1\u6a21\u5f0f\u6765\u4ee3\u66ff memento \u8bbe\u8ba1\u6a21\u5f0f\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Prototype registry can also be implemented using generics:<br \/>\n\u539f\u578b\u6ce8\u518c\u8868\u4e5f\u53ef\u4ee5\u4f7f\u7528\u6cdb\u578b\u5b9e\u73b0\uff1a<\/p>\n<pre><code>public interface IPrototypeRegistry\n{\nvoid Add&lt;T&gt;(T obj) where T : ICloneable;\nT Get&lt;T&gt;() where T : ICloneable;\n}<\/code><\/pre>\n<\/li>\n<li>\n<p>Consequences: Advantages<br \/>\n\u540e\u679c\uff1a\u4f18\u52bf<\/p>\n<\/li>\n<li>\n<p>Repetitive codes for creating objects are removed, and we are faced with a smaller amount of code.<br \/>\n\u7528\u4e8e\u521b\u5efa\u5bf9\u8c61\u7684\u91cd\u590d\u4ee3\u7801\u88ab\u5220\u9664\uff0c\u6211\u4eec\u9762\u4e34\u7684\u4ee3\u7801\u91cf\u8f83\u5c0f\u3002<\/p>\n<\/li>\n<li>\n<p>Due to the presence of the copying method, making complex objects can be easy.<br \/>\n\u7531\u4e8e\u5b58\u5728\u590d\u5236\u65b9\u6cd5\uff0c\u5236\u4f5c\u590d\u6742\u5bf9\u8c61\u5f88\u5bb9\u6613\u3002<\/p>\n<\/li>\n<li>\n<p>Objects can be copied, and a new object can be created without the need for a concrete class.<br \/>\n\u53ef\u4ee5\u590d\u5236\u5bf9\u8c61\uff0c\u5e76\u4e14\u53ef\u4ee5\u5728\u4e0d\u9700\u8981\u5177\u4f53\u7c7b\u7684\u60c5\u51b5\u4e0b\u521b\u5efa\u65b0\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>Consequences: Disadvantages<br \/>\n\u7ed3\u679c\uff1a\u7f3a\u70b9<\/p>\n<\/li>\n<li>\n<p>The process of copying objects can be complicated.<br \/>\n\u590d\u5236\u5bf9\u8c61\u7684\u8fc7\u7a0b\u53ef\u80fd\u5f88\u590d\u6742\u3002<\/p>\n<\/li>\n<li>\n<p>Implementing the copy process for classes that have circular dependencies can be complicated.<br \/>\n\u4e3a\u5177\u6709\u5faa\u73af\u4f9d\u8d56\u5173\u7cfb\u7684\u7c7b\u5b9e\u73b0\u590d\u5236\u8fc7\u7a0b\u53ef\u80fd\u5f88\u590d\u6742\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Applicability:<br \/>\n\u9002\u7528\u6027\uff1a<\/p>\n<ul>\n<li>When the type of object to be created is determined at runtime. For example, Dynamic Loading<br \/>\n\u5728\u8fd0\u884c\u65f6\u786e\u5b9a\u8981\u521b\u5efa\u7684\u5bf9\u8c61\u7684\u7c7b\u578b\u65f6\u3002\u4f8b\u5982\uff0cDynamic Loading<\/li>\n<li>When the objects of a class have almost the same data content<br \/>\n\u5f53\u4e00\u4e2a\u7c7b\u7684\u5bf9\u8c61\u5177\u6709\u51e0\u4e4e\u76f8\u540c\u7684\u6570\u636e\u5185\u5bb9\u65f6<\/li>\n<\/ul>\n<p>Related patterns:<br \/>\n\u76f8\u5173\u6a21\u5f0f\uff1a<br \/>\nSome of the following design patterns are not related to prototype design patterns, but to implement this design pattern, checking the following design patterns will be useful:<br \/>\n\u4ee5\u4e0b\u4e00\u4e9b\u8bbe\u8ba1\u6a21\u5f0f\u4e0e\u539f\u578b\u8bbe\u8ba1\u6a21\u5f0f\u65e0\u5173\uff0c\u4f46\u8981\u5b9e\u73b0\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u68c0\u67e5\u4ee5\u4e0b\u8bbe\u8ba1\u6a21\u5f0f\u5c06\u5f88\u6709\u7528\uff1a<\/p>\n<ul>\n<li>Singleton<\/li>\n<li>Command<\/li>\n<li>Memento<\/li>\n<li>Abstract factory<\/li>\n<\/ul>\n<h2>Singleton<\/h2>\n<h2>\u5355\u4f8b<\/h2>\n<p>In this section, the singleton design pattern is introduced and analyzed according to the structure presented in the GoF design patterns section in Chapter 1, Introduction to Design Pattern.<br \/>\n\u5728\u672c\u8282\u4e2d\uff0c\u6839\u636e\u7b2c 1 \u7ae0 \u8bbe\u8ba1\u6a21\u5f0f\u7b80\u4ecb\u7684 GoF \u8bbe\u8ba1\u6a21\u5f0f\u90e8\u5206\u4e2d\u4ecb\u7ecd\u7684\u7ed3\u6784\u4ecb\u7ecd\u548c\u5206\u6790\u4e86\u5355\u4f8b\u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<p>Name:<br \/>\nSingleton<br \/>\n\u5355\u4f8b<br \/>\nClassification:<br \/>\nCreational design patterns<br \/>\n\u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f<br \/>\nAlso known as:<br \/>\n-<br \/>\nIntent:<br \/>\nThis design pattern tries to provide a structure in which there is always an object of the class. One of the most important reasons for having only one object of a class is to control access to common resources such as databases and the like.<br \/>\n\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u5c1d\u8bd5\u63d0\u4f9b\u4e00\u4e2a\u7ed3\u6784\uff0c\u5176\u4e2d\u59cb\u7ec8\u5b58\u5728\u7c7b\u7684\u5bf9\u8c61\u3002\u53ea\u6709\u4e00\u4e2a\u7c7b\u5bf9\u8c61\u7684\u6700\u91cd\u8981\u539f\u56e0\u4e4b\u4e00\u662f\u63a7\u5236\u5bf9\u516c\u5171\u8d44\u6e90\uff08\u5982\u6570\u636e\u5e93\u7b49\uff09\u7684\u8bbf\u95ee\u3002<br \/>\nMotivation, Structure, Implementation, and Sample code:<br \/>\n\u52a8\u673a\u3001\u7ed3\u6784\u3001\u5b9e\u73b0\u548c\u793a\u4f8b\u4ee3\u7801\uff1a<br \/>\nSuppose we want to design the appropriate infrastructure for communication with the SQL Server database. For this purpose, we have created the DbConnectionManager class. During the program, to use this class, we need to always have only one object of it. In this scenario, the database is the shared resource. With these explanations, the following design can be imagined:<br \/>\n\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u8bbe\u8ba1\u9002\u5f53\u7684\u57fa\u7840\u7ed3\u6784\u6765\u4e0e SQL Server \u6570\u636e\u5e93\u8fdb\u884c\u901a\u4fe1\u3002\u4e3a\u6b64\uff0c\u6211\u4eec\u521b\u5efa\u4e86 DbConnectionManager \u7c7b\u3002\u5728\u7a0b\u5e8f\u8fc7\u7a0b\u4e2d\uff0c\u8981\u4f7f\u7528\u8fd9\u4e2a\u7c7b\uff0c\u6211\u4eec\u53ea\u9700\u8981\u53ea\u6709\u4e00\u4e2a\u5bf9\u8c61\u3002\u5728\u6b64\u65b9\u6848\u4e2d\uff0c\u6570\u636e\u5e93\u662f\u5171\u4eab\u8d44\u6e90\u3002\u901a\u8fc7\u8fd9\u4e9b\u89e3\u91ca\uff0c\u53ef\u4ee5\u60f3\u8c61\u51fa\u4ee5\u4e0b\u8bbe\u8ba1\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0213.png\" alt=\"alt text\" \/><br \/>\nFigure 2.13: Database connection manager initial relation<br \/>\n\u56fe 2.13.. \u6570\u636e\u5e93\u8fde\u63a5\u7ba1\u7406\u5668\u521d\u59cb\u5173\u7cfb<\/p>\n<p>According to Figure 2.13, the following code could be considered:<br \/>\n\u6839\u636e\u56fe 2.13\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class DbConnectionManager\n{\n    private DbConnectionManager() { }\n    public static DbConnectionManager GetInstance() =&gt; new();\n}<\/code><\/pre>\n<p>As you can see in Figure 2.13 class diagram and preceding code, the constructor of the class is defined with a private access modifier. The reason for this is to remove access to the constructor from outside the class. Because when the constructor of the class is called, an object must be returned, which can ruin the design. Therefore, to prevent this from happening, access to the class\u2019s constructor is limited. Within the class, the GetInstance method is defined as public static. So, it is possible to access this method outside the class without creating an object of the desired class type. In fact, this method will be responsible for presenting the object to the outside.<\/p>\n<p>\u5982\u56fe 2.13 \u7c7b\u56fe\u548c\u524d\u9762\u7684\u4ee3\u7801\u6240\u793a\uff0c\u7c7b\u7684\u6784\u9020\u51fd\u6570\u662f\u4f7f\u7528 private \u8bbf\u95ee\u4fee\u9970\u7b26\u5b9a\u4e49\u7684\u3002\u8fd9\u6837\u505a\u7684\u539f\u56e0\u662f\u4ece\u7c7b\u5916\u90e8\u5220\u9664\u5bf9\u6784\u9020\u51fd\u6570\u7684\u8bbf\u95ee\u3002\u56e0\u4e3a\u5f53\u8c03\u7528\u7c7b\u7684\u6784\u9020\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u8fd4\u56de\u4e00\u4e2a\u5bf9\u8c61\uff0c\u8fd9\u53ef\u80fd\u4f1a\u7834\u574f\u8bbe\u8ba1\u3002\u56e0\u6b64\uff0c\u4e3a\u4e86\u9632\u6b62\u8fd9\u79cd\u60c5\u51b5\u53d1\u751f\uff0c\u5bf9\u7c7b\u7684\u6784\u9020\u51fd\u6570\u7684\u8bbf\u95ee\u53d7\u5230\u9650\u5236\u3002\u5728\u8be5\u7c7b\u4e2d\uff0cGetInstance \u65b9\u6cd5\u5b9a\u4e49\u4e3a public static\u3002\u56e0\u6b64\uff0c\u53ef\u4ee5\u5728\u7c7b\u5916\u90e8\u8bbf\u95ee\u6b64\u65b9\u6cd5\uff0c\u800c\u65e0\u9700\u521b\u5efa\u6240\u9700\u7c7b\u7c7b\u578b\u7684\u5bf9\u8c61\u3002\u5b9e\u9645\u4e0a\uff0c\u6b64\u65b9\u6cd5\u5c06\u8d1f\u8d23\u5c06\u5bf9\u8c61\u5448\u73b0\u7ed9\u5916\u90e8\u3002<\/p>\n<p>The preceding code still does not cover the main requirement, which is to have only one object. Because every time the GetInstance method is called, a new object is always created and returned. The following code shows how to use this class and the existing problem:<\/p>\n<p>\u524d\u9762\u7684\u4ee3\u7801\u4ecd\u7136\u6ca1\u6709\u6db5\u76d6\u4e3b\u8981\u8981\u6c42\uff0c\u5373\u53ea\u6709\u4e00\u4e2a\u5bf9\u8c61\u3002\u56e0\u4e3a\u6bcf\u6b21\u8c03\u7528 GetInstance \u65b9\u6cd5\u65f6\uff0c\u603b\u662f\u4f1a\u521b\u5efa\u5e76\u8fd4\u56de\u4e00\u4e2a\u65b0\u5bf9\u8c61\u3002\u4e0b\u9762\u7684\u4ee3\u7801\u6f14\u793a\u5982\u4f55\u4f7f\u7528\u6b64\u7c7b\u548c\u73b0\u6709\u95ee\u9898\uff1a<\/p>\n<pre><code>DbConnectionManager obj1 = DbConnectionManager.GetInstance();\n\nDbConnectionManager obj2 = DbConnectionManager.GetInstance();\n\nConsole.WriteLine($&quot;obj1: {obj1.GetHashCode()}, obj2: {obj2.GetHashCode()}&quot;);<\/code><\/pre>\n<p>Output:<br \/>\n\u8f93\u51fa\uff1a<\/p>\n<pre><code>obj1: 58225482, obj2: 54267293<\/code><\/pre>\n<p>As shown in the preceding code and its corresponding output, two different objects have been created. To prevent this, we need to slightly change the GetInstance method:<br \/>\n\u5982\u524d\u9762\u7684\u4ee3\u7801\u53ca\u5176\u76f8\u5e94\u7684\u8f93\u51fa\u6240\u793a\uff0c\u5df2\u7ecf\u521b\u5efa\u4e86\u4e24\u4e2a\u4e0d\u540c\u7684\u5bf9\u8c61\u3002\u4e3a\u4e86\u9632\u6b62\u8fd9\u79cd\u60c5\u51b5\uff0c\u6211\u4eec\u9700\u8981\u7a0d\u5fae\u66f4\u6539 GetInstance \u65b9\u6cd5\uff1a<\/p>\n<ul>\n<li>The first step of the change is to return the object directly to the user after it is created and save it in a variable, and<br \/>\n\u66f4\u6539\u7684\u7b2c\u4e00\u6b65\u662f\u5728\u521b\u5efa\u5bf9\u8c61\u540e\u76f4\u63a5\u5c06\u5bf9\u8c61\u8fd4\u56de\u7ed9\u7528\u6237\uff0c\u5e76\u5c06\u5176\u4fdd\u5b58\u5728\u53d8\u91cf\u4e2d\uff0c<\/li>\n<li>The second step is to check before creating the object; if this variable contains the object, no more new objects will be created.<br \/>\n\u7b2c\u4e8c\u6b65\u662f\u5728\u521b\u5efa\u5bf9\u8c61\u4e4b\u524d\u8fdb\u884c\u68c0\u67e5;\u5982\u679c\u6b64\u53d8\u91cf\u5305\u542b\u5bf9\u8c61\uff0c\u5219\u4e0d\u4f1a\u518d\u521b\u5efa\u65b0\u5bf9\u8c61\u3002<\/li>\n<li>Therefore, the class diagram and code will change as the following:<br \/>\n\u56e0\u6b64\uff0c\u7c7b\u56fe\u548c\u4ee3\u7801\u5c06\u66f4\u6539\u5982\u4e0b\uff1a<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"\/net7designpatternsindepth\/0214.png\" alt=\"alt text\" \/><br \/>\nFigure 2.14: Singleton design pattern UML diagram<br \/>\n\u56fe 2.14\uff1a \u5355\u4f8b\u8bbe\u8ba1\u6a21\u5f0f UML \u56fe<\/p>\n<p>According to Figure 2.14, the following code could be considered:<\/p>\n<p>\u6839\u636e\u56fe 2.14\uff0c\u53ef\u4ee5\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><code>public class DbConnectionManager\n{\n    private static DbConnectionManager _instance;\n    private DbConnectionManager() { }\n    public static DbConnectionManager GetInstance()\n    {\n        if (_instance == null)\n        _instance = new();\n        return _instance;\n    }\n}<\/code><\/pre>\n<p>Now if we run these codes again, we have the following output:<br \/>\n\u73b0\u5728\uff0c\u5982\u679c\u6211\u4eec\u518d\u6b21\u8fd0\u884c\u8fd9\u4e9b\u4ee3\u7801\uff0c\u6211\u4eec\u5c06\u5f97\u5230\u4ee5\u4e0b\u8f93\u51fa\uff1a<\/p>\n<pre><code>obj1: 58225482, obj2: 58225482<\/code><\/pre>\n<p>As you can see, only one object of DbConnectionManager class is created and available. This way of implementing the singleton design pattern is suitable for single and multi-thread environments. This implementation needs changes, and this design pattern should be implemented in a thread-safe manner. If this design pattern is implemented using the early initialization method, the problem raised for multi-thread environments will not exist, and the desired object will be created for each AppDomain.<\/p>\n<p>\u5982\u60a8\u6240\u89c1\uff0c\u4ec5\u521b\u5efa\u4e00\u4e2a DbConnectionManager \u7c7b\u7684\u5bf9\u8c61\u4e14\u53ef\u7528\u3002\u8fd9\u79cd\u5b9e\u73b0\u5355\u4f8b\u8bbe\u8ba1\u6a21\u5f0f\u7684\u65b9\u5f0f\u9002\u7528\u4e8e\u5355\u7ebf\u7a0b\u548c\u591a\u7ebf\u7a0b\u73af\u5883\u3002\u6b64\u5b9e\u73b0\u9700\u8981\u66f4\u6539\uff0c\u5e76\u4e14\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u5e94\u4ee5\u7ebf\u7a0b\u5b89\u5168\u7684\u65b9\u5f0f\u5b9e\u73b0\u3002\u5982\u679c\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u662f\u4f7f\u7528\u65e9\u671f\u521d\u59cb\u5316\u65b9\u6cd5\u5b9e\u73b0\u7684\uff0c\u5219\u4e3a\u591a\u7ebf\u7a0b\u73af\u5883\u5f15\u53d1\u7684\u95ee\u9898\u5c06\u4e0d\u5b58\u5728\uff0c\u5e76\u4e14\u5c06\u4e3a\u6bcf\u4e2a AppDomain \u521b\u5efa\u6240\u9700\u7684\u5bf9\u8c61\u3002<\/p>\n<p>Before dealing with the implementation of thread Safe, let us first observe the problem by simulating the multi-thread environment:<br \/>\n\u5728\u5904\u7406\u7ebf\u7a0b Safe \u7684\u5b9e\u73b0\u4e4b\u524d\uff0c\u6211\u4eec\u5148\u901a\u8fc7\u6a21\u62df\u591a\u7ebf\u7a0b\u73af\u5883\u6765\u89c2\u5bdf\u95ee\u9898\uff1a<\/p>\n<pre><code>Parallel.Invoke(() =&gt;\n    {\n    DbConnectionManager obj1 = DbConnectionManager.GetInstance();\n    Console.WriteLine($&quot;obj1: {obj1.GetHashCode()}&quot;);\n    }, () =&gt;\n        {\n        DbConnectionManager obj2 = DbConnectionManager.GetInstance();\n        Console.WriteLine($&quot;obj2: {obj2.GetHashCode()}&quot;);\n        });<\/code><\/pre>\n<p>The Invoke method in the Parallel class tries to perform the provided tasks in parallel. By running the preceding code, we can see the output as follows:<br \/>\nParallel \u7c7b\u4e2d\u7684 Invoke \u65b9\u6cd5\u5c1d\u8bd5\u5e76\u884c\u6267\u884c\u63d0\u4f9b\u7684\u4efb\u52a1\u3002\u901a\u8fc7\u8fd0\u884c\u4e0a\u8ff0\u4ee3\u7801\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u5982\u4e0b\u8f93\u51fa\uff1a<\/p>\n<pre><code>obj2: 6044116\n\nobj1: 27252167<\/code><\/pre>\n<p>Pay attention that these outputs may be different on different machines. The preceding output shows that the first obj2 is prepared, and then obj1 is prepared. Since these two objects have different HashCodes, we can conclude that even though the singleton pattern is used, in the multi-thread environment, instead of just one object, we are faced with several objects. Now, to solve this problem, as mentioned before, we need to implement Singleton as thread Safe. There are different ways to implement Singleton as thread Safe. We do this using the lock block. For this purpose, the DbConnectionManager class is changed as follows:<\/p>\n<p>\u8bf7\u6ce8\u610f\uff0c\u8fd9\u4e9b\u8f93\u51fa\u5728\u4e0d\u540c\u8ba1\u7b97\u673a\u4e0a\u53ef\u80fd\u6709\u6240\u4e0d\u540c\u3002\u4ece\u4e0a\u8ff0\u8f93\u51fa\u53ef\u4ee5\u770b\u51fa\uff0c\u5148\u51c6\u5907\u4e86\u7b2c\u4e00\u4e2a obj2\uff0c\u7136\u540e\u51c6\u5907\u4e86 obj1\u3002\u7531\u4e8e\u8fd9\u4e24\u4e2a\u5bf9\u8c61\u5177\u6709\u4e0d\u540c\u7684 HashCodes\uff0c\u6211\u4eec\u53ef\u4ee5\u5f97\u51fa\u7ed3\u8bba\uff0c\u5373\u4f7f\u4f7f\u7528\u4e86\u5355\u4f8b\u6a21\u5f0f\uff0c\u5728\u591a\u7ebf\u7a0b\u73af\u5883\u4e2d\uff0c\u6211\u4eec\u9762\u5bf9\u7684\u4e0d\u4ec5\u4ec5\u662f\u4e00\u4e2a\u5bf9\u8c61\uff0c\u800c\u662f\u591a\u4e2a\u5bf9\u8c61\u3002\u73b0\u5728\uff0c\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u5982\u524d\u6240\u8ff0\uff0c\u6211\u4eec\u9700\u8981\u5c06 Singleton \u5b9e\u73b0\u4e3a thread Safe\u3002\u6709\u591a\u79cd\u65b9\u6cd5\u53ef\u4ee5\u5c06 Singleton \u5b9e\u73b0\u4e3a thread Safe\u3002\u6211\u4eec\u4f7f\u7528 lock \u5757\u6765\u505a\u5230\u8fd9\u4e00\u70b9\u3002\u4e3a\u6b64\uff0cDbConnectionManager \u7c7b\u66f4\u6539\u5982\u4e0b\uff1a<\/p>\n<pre><code>public class DbConnectionManager\n{\n    private static DbConnectionManager _instance;\n    private static object locker = new();\n    private DbConnectionManager() { }\n    public static DbConnectionManager GetInstance()\n    {\n        lock (locker)\n            {\n                if (_instance == null)\n                _instance = new();\n                return _instance;\n            }\n    }\n}<\/code><\/pre>\n<p>In the preceding code, by using the lock block, the first thread that launches the method takes over the locker resource and enters the lock block. The remaining threads that enter the method, because the locker resource is not available are stopped so that the previous thread releases the resource. Immediately after releasing the resource, the next thread receives the resource and enters the lock block. The problem of not being thread-safe is solved, but the code still can be improved. The important problem of this implementation method is efficiency.<\/p>\n<p>\u5728\u4e0a\u9762\u7684\u4ee3\u7801\u4e2d\uff0c\u901a\u8fc7\u4f7f\u7528 lock \u5757\uff0c\u542f\u52a8\u8be5\u65b9\u6cd5\u7684\u7b2c\u4e00\u4e2a\u7ebf\u7a0b\u5c06\u63a5\u7ba1 locker \u8d44\u6e90\u5e76\u8fdb\u5165 lock \u5757\u3002\u7531\u4e8e locker \u8d44\u6e90\u4e0d\u53ef\u7528\uff0c\u56e0\u6b64\u8fdb\u5165\u8be5\u65b9\u6cd5\u7684\u5176\u4f59\u7ebf\u7a0b\u5c06\u505c\u6b62\uff0c\u4ee5\u4fbf\u524d\u4e00\u4e2a\u7ebf\u7a0b\u91ca\u653e\u8d44\u6e90\u3002\u91ca\u653e\u8d44\u6e90\u540e\uff0c\u4e0b\u4e00\u4e2a\u7ebf\u7a0b\u7acb\u5373\u6536\u5230\u8d44\u6e90\u5e76\u8fdb\u5165 lock \u5757\u3002\u7ebf\u7a0b\u4e0d\u5b89\u5168\u7684\u95ee\u9898\u5f97\u5230\u4e86\u89e3\u51b3\uff0c\u4f46\u4ee3\u7801\u4ecd\u7136\u53ef\u4ee5\u6539\u8fdb\u3002\u8fd9\u79cd\u5b9e\u73b0\u65b9\u6cd5\u7684\u91cd\u8981\u95ee\u9898\u662f\u6548\u7387\u3002<\/p>\n<p>For example, thread number 1 enters the GetInstance method and receives the locker. Thread number 2 enters and stops behind the lock block. Thread number 1 creates the object and exits the block, and thread number 2 enters the lock block. Meanwhile, thread number 3 enters the GetInstance method, and since the locker is owned by thread number 2, it must wait. But the waiting is useless, and thread number 3 can directly receive the object and return it. With this explanation, the preceding code can be optimized as follows:<\/p>\n<p>\u4f8b\u5982\uff0c\u7ebf\u7a0b 1 \u8f93\u5165 GetInstance \u65b9\u6cd5\u5e76\u63a5\u6536\u4fdd\u9669\u7bb1\u3002\u7ebf\u7a0b 2 \u8fdb\u5165\u5e76\u505c\u6b62\u5728\u9501\u5757\u540e\u9762\u3002\u7ebf\u7a0b 1 \u521b\u5efa\u5bf9\u8c61\u5e76\u9000\u51fa\u5757\uff0c\u7ebf\u7a0b 2 \u8fdb\u5165 lock \u5757\u3002\u540c\u65f6\uff0c\u7ebf\u7a0b 3 \u8fdb\u5165 GetInstance \u65b9\u6cd5\uff0c\u5e76\u4e14\u7531\u4e8e\u9501\u7531\u7ebf\u7a0b 2 \u62e5\u6709\uff0c\u56e0\u6b64\u5b83\u5fc5\u987b\u7b49\u5f85\u3002\u4f46\u662f\u7b49\u5f85\u6ca1\u7528\uff0c\u7ebf\u7a0b 3 \u53ef\u4ee5\u76f4\u63a5\u63a5\u6536\u5bf9\u8c61\u5e76\u8fd4\u56de\u3002\u901a\u8fc7\u6b64\u8bf4\u660e\uff0c\u53ef\u4ee5\u6309\u5982\u4e0b\u65b9\u5f0f\u4f18\u5316\u4e0a\u8ff0\u4ee3\u7801\uff1a<\/p>\n<pre><code>public static DbConnectionManager GetInstance()\n{\n    if (_instance != null)\n    return _instance;\n    lock (locker)\n    {\n        if (_instance == null)\n        _instance = new();\n        return _instance;\n    }\n}<\/code><\/pre>\n<p>This method is called double-check locking and can improve overall performance.<br \/>\n\u6b64\u65b9\u6cd5\u79f0\u4e3a double-check locking\uff0c\u53ef\u4ee5\u63d0\u9ad8\u6574\u4f53\u6027\u80fd\u3002<\/p>\n<p>The second method to implement thread-safe is to mark the GetInstance method as Synchronized. Using this method, the GetInstance method is implemented as follows:<br \/>\n\u5b9e\u73b0\u7ebf\u7a0b\u5b89\u5168\u7684\u7b2c\u4e8c\u79cd\u65b9\u6cd5\u662f\u5c06 GetInstance \u65b9\u6cd5\u6807\u8bb0\u4e3a Synchronized\u3002\u4f7f\u7528\u6b64\u65b9\u6cd5\uff0cGetInstance \u65b9\u6cd5\u7684\u5b9e\u73b0\u65b9\u5f0f\u5982\u4e0b\uff1a<\/p>\n<pre><code>[MethodImpl(MethodImplOptions.Synchronized)]\npublic static DbConnectionManager GetInstance()\n{\n    if (_instance == null)\n    _instance = new();\n    return _instance;\n}<\/code><\/pre>\n<p>This method has an important difference compared to the lock method; that is, only one thread is allowed to enter the method. The object is protected by using a lock, and the whole method is protected by using a synchronized method.<\/p>\n<p>\u4e0e lock \u65b9\u6cd5\u76f8\u6bd4\uff0c\u6b64\u65b9\u6cd5\u5177\u6709\u91cd\u8981\u533a\u522b;\u4e5f\u5c31\u662f\u8bf4\uff0c\u53ea\u5141\u8bb8\u4e00\u4e2a\u7ebf\u7a0b\u8fdb\u5165\u8be5\u65b9\u6cd5\u3002\u4f7f\u7528\u9501\u4fdd\u62a4\u5bf9\u8c61\uff0c\u5e76\u4f7f\u7528\u540c\u6b65\u65b9\u6cd5\u4fdd\u62a4\u6574\u4e2a\u65b9\u6cd5\u3002<\/p>\n<p>Apart from the preceding methods, there are other methods, such as using Lazy<T> or Monitor class to implement a thread-safe singleton.<br \/>\n\u9664\u4e86\u4e0a\u8ff0\u65b9\u6cd5\u5916\uff0c\u8fd8\u6709\u5176\u4ed6\u65b9\u6cd5\uff0c\u4f8b\u5982\u4f7f\u7528 Lazy \u6216 Monitor \u7c7b\u6765\u5b9e\u73b0\u7ebf\u7a0b\u5b89\u5168\u7684\u5355\u4f8b\u3002<\/p>\n<p>Participants:<br \/>\n\u53c2\u4e0e\u8005\uff1a<\/p>\n<ul>\n<li>Singleton: In the preceding scenario, it is the DbConnectionManager that is responsible for defining the object creation process. This class should always try to create only one object of the target class.<br \/>\nSingleton\uff1a\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\uff0cDbConnectionManager \u8d1f\u8d23\u5b9a\u4e49\u5bf9\u8c61\u521b\u5efa\u8fc7\u7a0b\u3002\u6b64\u7c7b\u5e94\u59cb\u7ec8\u5c1d\u8bd5\u4ec5\u521b\u5efa\u76ee\u6807\u7c7b\u7684\u4e00\u4e2a\u5bf9\u8c61\u3002<\/li>\n<\/ul>\n<p>Notes:<\/p>\n<ul>\n<li>\n<p>By using this design pattern, in the object creation process, any changes which are needed can be applied by applying changes in the GetInstance method. For example, by having this structure, it is possible to provide conditions so that there are always two objects from a class. To implement this logic, it is enough to change the GetInstance method.<br \/>\n\u901a\u8fc7\u4f7f\u7528\u8fd9\u79cd\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5728\u5bf9\u8c61\u521b\u5efa\u8fc7\u7a0b\u4e2d\uff0c\u53ef\u4ee5\u901a\u8fc7\u5728 GetInstance \u65b9\u6cd5\u4e2d\u5e94\u7528\u66f4\u6539\u6765\u5e94\u7528\u6240\u9700\u7684\u4efb\u4f55\u66f4\u6539\u3002\u4f8b\u5982\uff0c\u901a\u8fc7\u5177\u6709\u6b64\u7ed3\u6784\uff0c\u53ef\u4ee5\u63d0\u4f9b\u6761\u4ef6\uff0c\u4ee5\u4fbf\u4e00\u4e2a\u7c7b\u4e2d\u59cb\u7ec8\u6709\u4e24\u4e2a\u5bf9\u8c61\u3002\u8981\u5b9e\u73b0\u6b64\u903b\u8f91\uff0c\u53ea\u9700\u66f4\u6539 GetInstance \u65b9\u6cd5\u5373\u53ef\u3002<\/p>\n<\/li>\n<li>\n<p>In using this design pattern, you should pay attention to its difference from static classes. Among the most important differences between the static class and the use of the singleton design pattern, we can mention the impossibility of using static classes in inheritance, which makes static classes not extensible.<br \/>\n\u5728\u4f7f\u7528\u6b64\u8bbe\u8ba1\u6a21\u5f0f\u65f6\uff0c\u5e94\u6ce8\u610f\u5b83\u4e0e static \u7c7b\u7684\u533a\u522b\u3002\u5728 static \u7c7b\u548c\u4f7f\u7528 singleton \u8bbe\u8ba1\u6a21\u5f0f\u4e4b\u95f4\u6700\u91cd\u8981\u7684\u533a\u522b\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u63d0\u5230\u5728\u7ee7\u627f\u4e2d\u4f7f\u7528 static \u7c7b\u662f\u4e0d\u53ef\u80fd\u7684\uff0c\u8fd9\u4f7f\u5f97 static \u7c7b\u4e0d\u53ef\u6269\u5c55\u3002<\/p>\n<\/li>\n<li>\n<p>Abstract factory, factory method, and builder design patterns can be implemented using Singleton.<br \/>\n\u62bd\u8c61\u5de5\u5382\u3001\u5de5\u5382\u65b9\u6cd5\u548c\u6784\u5efa\u5668\u8bbe\u8ba1\u6a21\u5f0f\u53ef\u4ee5\u4f7f\u7528 Singleton \u5b9e\u73b0\u3002<\/p>\n<\/li>\n<li>\n<p>The initialization process can be implemented in both Lazy and Early. The difference between these two methods is when the desired object is initialized. In the Lazy method, the object is initialized when it is needed. In the Early method, the object is initialized when the class is loaded. The lazy method is used in the preceding scenario. To implement the early method, you can do the following:<br \/>\n\u521d\u59cb\u5316\u8fc7\u7a0b\u53ef\u4ee5\u5728 Lazy \u548c Early \u4e2d\u5b9e\u73b0\u3002\u8fd9\u4e24\u79cd\u65b9\u6cd5\u4e4b\u95f4\u7684\u533a\u522b\u5728\u4e8e\u521d\u59cb\u5316\u6240\u9700\u5bf9\u8c61\u7684\u65f6\u95f4\u3002\u5728 Lazy \u65b9\u6cd5\u4e2d\uff0c\u5bf9\u8c61\u5728\u9700\u8981\u65f6\u521d\u59cb\u5316\u3002\u5728 Early \u65b9\u6cd5\u4e2d\uff0c\u5bf9\u8c61\u5728\u52a0\u8f7d\u7c7b\u65f6\u521d\u59cb\u5316\u3002\u5728\u524d\u9762\u7684\u573a\u666f\u4e2d\u4f7f\u7528\u4e86 lazy \u65b9\u6cd5\u3002\u8981\u5b9e\u73b0\u65e9\u671f\u65b9\u6cd5\uff0c\u60a8\u53ef\u4ee5\u6267\u884c\u4ee5\u4e0b\u4f5c\uff1a<\/p>\n<pre><code>public class DbConnectionManager\n{\nprivate static DbConnectionManager _instance = new();\nprivate DbConnectionManager() { }\npublic static DbConnectionManager GetInstance() =&gt; _instance;\n}<\/code><\/pre>\n<\/li>\n<\/ul>\n<p>Consequences: Advantages<br \/>\n\u540e\u679c\uff1a\u4f18\u52bf<\/p>\n<ul>\n<li>\n<p>It can be ensured that there is one object in the class.<br \/>\n\u53ef\u4ee5\u786e\u4fdd\u7c7b\u4e2d\u6709\u4e00\u4e2a\u5bf9\u8c61\u3002<\/p>\n<\/li>\n<li>\n<p>It is possible to access the object. Since a method is responsible for providing the object, it is possible to have better control over who requested the object and when.<br \/>\n\u53ef\u4ee5\u8bbf\u95ee\u8be5\u5bf9\u8c61\u3002\u7531\u4e8e\u65b9\u6cd5\u8d1f\u8d23\u63d0\u4f9b\u5bf9\u8c61\uff0c\u56e0\u6b64\u53ef\u4ee5\u66f4\u597d\u5730\u63a7\u5236\u8bf7\u6c42\u5bf9\u8c61\u7684\u4eba\u5458\u548c\u65f6\u95f4\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Consequences: Disadvantages<br \/>\n\u540e\u679c\uff1a\u7f3a\u70b9<\/p>\n<ul>\n<li>\n<p>The implementation of the thread-safe structure can be complicated, and this task can affect performance due to the use of locking mechanisms.<br \/>\n\u7ebf\u7a0b\u5b89\u5168\u7ed3\u6784\u7684\u5b9e\u73b0\u53ef\u80fd\u5f88\u590d\u6742\uff0c\u5e76\u4e14\u7531\u4e8e\u4f7f\u7528\u9501\u5b9a\u673a\u5236\uff0c\u6b64\u4efb\u52a1\u53ef\u80fd\u4f1a\u5f71\u54cd\u6027\u80fd\u3002<\/p>\n<\/li>\n<li>\n<p>Writing unit tests can be complicated.<br \/>\n\u7f16\u5199\u5355\u5143\u6d4b\u8bd5\u53ef\u80fd\u5f88\u590d\u6742\u3002<\/p>\n<\/li>\n<\/ul>\n<p>Applicability:<br \/>\n\u9002\u7528\u6027\uff1a<\/p>\n<ul>\n<li>When we need only one object of the class to be available to the user.<br \/>\n\u5f53\u6211\u4eec\u53ea\u9700\u8981 class \u7684\u4e00\u4e2a\u5bf9\u8c61\u53ef\u4f9b\u7528\u6237\u4f7f\u7528\u65f6\u3002<\/li>\n<li>When we need to have more control over the object and its data content, we can use this design pattern instead of using Global Variables.<br \/>\n\u5f53\u6211\u4eec\u9700\u8981\u5bf9\u5bf9\u8c61\u53ca\u5176\u6570\u636e\u5185\u5bb9\u8fdb\u884c\u66f4\u591a\u63a7\u5236\u65f6\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u79cd\u8bbe\u8ba1\u6a21\u5f0f\u800c\u4e0d\u662f\u4f7f\u7528 Global Variables\u3002<\/li>\n<\/ul>\n<p>Related patterns:<br \/>\n\u76f8\u5173\u6a21\u5f0f\uff1a<br \/>\nSome of the following design patterns are not related to the Singleton design pattern, but to implement this design pattern, checking the following design patterns will be useful:<br \/>\n\u4ee5\u4e0b\u4e00\u4e9b\u8bbe\u8ba1\u6a21\u5f0f\u4e0e Singleton \u8bbe\u8ba1\u6a21\u5f0f\u65e0\u5173\uff0c\u4f46\u8981\u5b9e\u73b0\u6b64\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u68c0\u67e5\u4ee5\u4e0b\u8bbe\u8ba1\u6a21\u5f0f\u5c06\u5f88\u6709\u7528\uff1a<\/p>\n<ul>\n<li>Facade<\/li>\n<li>Abstract Factory<\/li>\n<li>Factory Method<\/li>\n<li>Builder<\/li>\n<li>Prototype<\/li>\n<li>Flyweight<\/li>\n<li>Observer<\/li>\n<li>State<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<h2>\u603b\u7ed3<\/h2>\n<p>In this chapter, you got acquainted with various creational design patterns and learned how to manage the initialization of objects according to different conditions.<br \/>\n\u5728\u672c\u7ae0\u4e2d\uff0c\u60a8\u719f\u6089\u4e86\u5404\u79cd\u521b\u5efa\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5e76\u5b66\u4e60\u4e86\u5982\u4f55\u6839\u636e\u4e0d\u540c\u6761\u4ef6\u7ba1\u7406\u5bf9\u8c61\u7684\u521d\u59cb\u5316\u3002<\/p>\n<p>In the next chapter, you will learn about structural design patterns and learn how to manage relationships between classes and objects.<br \/>\n\u5728\u4e0b\u4e00\u7ae0\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u7ed3\u6784\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5e76\u5b66\u4e60\u5982\u4f55\u7ba1\u7406\u7c7b\u548c\u5bf9\u8c61\u4e4b\u95f4\u7684\u5173\u7cfb\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Chapter 2 Creational Design Patterns \u7b2c2\u7ae0 \u521b\u5efa\u5f0f\u8bbe\u8ba1\u6a21\u5f0f Introduction \u7b80\u4ecb As the name suggests, creational design patterns deal with object construction and how to create instances. In C# .NET programming language, a new keyword is used to create an object. To create an object, it is necessary to provide the name of the class. In other [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[21],"class_list":["post-693","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-net-7-design-patterns-in-depth"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/693","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=693"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/693\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}