{"id":10006923,"date":"2022-11-28T16:47:23","date_gmt":"2022-11-28T08:47:23","guid":{"rendered":"https:\/\/ityet.com\/?p=10006923"},"modified":"2022-11-28T16:47:23","modified_gmt":"2022-11-28T08:47:23","slug":"%e5%bf%ab%e6%94%b6%e8%97%8f%ef%bc%81%e6%9c%80%e5%85%a8go%e8%af%ad%e8%a8%80%e5%ae%9e%e7%8e%b0%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f%e3%80%90%e4%b8%8b%e3%80%91","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006923","title":{"rendered":"\u5feb\u6536\u85cf\uff01\u6700\u5168GO\u8bed\u8a00\u5b9e\u73b0\u8bbe\u8ba1\u6a21\u5f0f\u3010\u4e0b\u3011"},"content":{"rendered":"<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916586\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u5bfc\u8bed| \u7ee7\u4e0a\u7bc7\u3010<a href=\"https:\/\/link.segmentfault.com\/?enc=FK9LWx%2FmJmuqLBYLwFGiVA%3D%3D.5FhfWbpzEF1vLFL32y0NdbI90o8oIfWAIVO3rdO%2FM%2B65vEGzEZjskfmBC4wVFEhpEDtqVrwev%2BjUU5FyopLWfC8bHFb8J93CTv09u7L5kMYGF5AQCdI4oXt7ij2iEphOMZ5TpuaptFIiJ2IaNdVhpQAoAmNdNAShieh8fyPij1mR5UYyQSx93WgH7UTOMICNs67SaHQKZsA53sZL57LDwHK0vsRBgnJQKO5YULsOlEMitIaB5OrIdKgmdb6IhV7%2Foc4wpWCGaYL5AP7j42mN5KzCD32norU34ejbiqZqnVE%3D\" rel=\"nofollow\">\u5feb\u6536\u85cf\uff01\u6700\u5168GO\u8bed\u8a00\u5b9e\u73b0\u8bbe\u8ba1\u6a21\u5f0f<\/a>\u3011\uff0c\u672c\u6587\u7ee7\u7eed\u5217\u51faGO\u8bed\u8a00\u5b9e\u73b0\u7684\u7ecf\u5178\u8bbe\u8ba1\u6a21\u5f0f\u793a\u4f8b\uff0c\u6bcf\u4e2a\u793a\u4f8b\u90fd\u7cbe\u5fc3\u8bbe\u8ba1\uff0c\u529b\u6c42\u7b26\u5408\u6a21\u5f0f\u7ed3\u6784\uff0c\u53ef\u4f5c\u4e3a\u65e5\u5e38\u7f16\u7801\u53c2\u8003\uff0c\u540c\u65f6\u4e00\u4e9b\u5e38\u7528\u7684\u8bbe\u8ba1\u6a21\u5f0f\u878d\u5165\u4e86\u5f00\u53d1\u5b9e\u8df5\u7ecf\u9a8c\u603b\u7ed3\uff0c\u5e2e\u52a9\u5927\u5bb6\u5728\u5e73\u65f6\u5de5\u4f5c\u4e2d\u7075\u6d3b\u8fd0\u7528\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916587\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u89e3\u91ca\u5668\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u89e3\u91ca\u5668\u6a21\u5f0f\u7528\u4e8e\u63cf\u8ff0\u5982\u4f55\u4f7f\u7528\u9762\u5411\u5bf9\u8c61\u8bed\u8a00\u6784\u6210\u4e00\u4e2a\u7b80\u5355\u7684\u8bed\u8a00\u89e3\u91ca\u5668\u3002\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u4e3a\u4e86\u66f4\u597d\u5730\u63cf\u8ff0\u67d0\u4e00\u4e9b\u7279\u5b9a\u7c7b\u578b\u7684\u95ee\u9898\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u5efa\u4e00\u79cd\u65b0\u7684\u8bed\u8a00\uff0c\u8fd9\u79cd\u8bed\u8a00\u62e5\u6709\u81ea\u5df1\u7684\u8868\u8fbe\u5f0f\u548c\u7ed3\u6784\uff0c\u5373\u6587\u6cd5\u89c4\u5219\uff0c\u8fd9\u4e9b\u95ee\u9898\u7684\u5b9e\u4f8b\u5c06\u5bf9\u5e94\u4e3a\u8be5\u8bed\u8a00\u4e2d\u7684\u53e5\u5b50\u3002\u6b64\u65f6\uff0c\u53ef\u4ee5\u4f7f\u7528\u89e3\u91ca\u5668\u6a21\u5f0f\u6765\u8bbe\u8ba1\u8fd9\u79cd\u65b0\u7684\u8bed\u8a00\u3002\u5bf9\u89e3\u91ca\u5668\u6a21\u5f0f\u7684\u5b66\u4e60\u80fd\u591f\u52a0\u6df1\u6211\u4eec\u5bf9\u9762\u5411\u5bf9\u8c61\u601d\u60f3\u7684\u7406\u89e3\uff0c\u5e76\u4e14\u638c\u63e1\u7f16\u7a0b\u8bed\u8a00\u4e2d\u6587\u6cd5\u89c4\u5219\u7684\u89e3\u91ca\u8fc7\u7a0b\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u5b9a\u4e49\u4e00\u4e2a\u89e3\u6790\u7279\u5f81\u503c\u7684\u8bed\u53e5\u89e3\u91ca\u5668\uff0c\u63d0\u4f9b\u662f\u5426\u5305\u542b\u7279\u5f81\u503c\u7684\u7ec8\u7ed3\u8868\u8fbe\u5f0f\uff0c\u5e76\u63d0\u4f9b\u6216\u8868\u8fbe\u5f0f\u4e0e\u4e14\u8868\u8fbe\u5f0f\uff0c\u540c\u65f6\uff0c\u751f\u6210\u5357\u6781\u6d32\u7279\u5f81\u5224\u65ad\u8868\u8fbe\u5f0f\uff0c\u53ca\u7f8e\u56fd\u4eba\u7279\u5f81\u5224\u65ad\u8868\u8fbe\u5f0f\uff0c\u6700\u540e\u6d4b\u8bd5\u7a0b\u5e8f\u6839\u636e\u5bf9\u8c61\u7279\u5f81\u503c\u63cf\u8ff0\uff0c\u901a\u8fc7\u8868\u8fbe\u5f0f\u5224\u65ad\u662f\u5426\u4e3a\u771f\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u7279\u5f81\u503c\u89e3\u91ca\u5668<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package interpreter\n\nimport &quot;strings&quot;\n\n\/\/ Expression \u8868\u8fbe\u5f0f\u63a5\u53e3\uff0c\u5305\u542b\u4e00\u4e2a\u89e3\u91ca\u65b9\u6cd5\ntype Expression interface {\n  Interpret(context string) bool\n}\n\n\/\/ terminalExpression \u7ec8\u7ed3\u7b26\u8868\u8fbe\u5f0f\uff0c\u5224\u65ad\u8868\u8fbe\u5f0f\u4e2d\u662f\u5426\u5305\u542b\u5339\u914d\u6570\u636e\ntype terminalExpression struct {\n  matchData string\n}\n\nfunc NewTerminalExpression(matchData string) *terminalExpression {\n  return &amp;terminalExpression{matchData: matchData}\n}\n\n\/\/ Interpret \u5224\u65ad\u662f\u5426\u5305\u542b\u5339\u914d\u5b57\u7b26\nfunc (t *terminalExpression) Interpret(context string) bool {\n  if strings.Contains(context, t.matchData) {\n    return true\n  }\n  return false\n}\n\n\/\/ orExpression \u6216\u8868\u8fbe\u5f0f\ntype orExpression struct {\n  left, right Expression\n}\n\nfunc NewOrExpression(left, right Expression) *orExpression {\n  return &amp;orExpression{\n    left:  left,\n    right: right,\n  }\n}\n\nfunc (o *orExpression) Interpret(context string) bool {\n  return o.left.Interpret(context) || o.right.Interpret(context)\n}\n\n\/\/ andExpression \u4e0e\u8868\u8fbe\u5f0f\ntype andExpression struct {\n  left, right Expression\n}\n\nfunc NewAndExpression(left, right Expression) *andExpression {\n  return &amp;andExpression{\n    left:  left,\n    right: right,\n  }\n}\n\nfunc (o *andExpression) Interpret(context string) bool {\n  return o.left.Interpret(context) &amp;&amp; o.right.Interpret(context)\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package interpreter\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestInterpreter(t *testing.T) {\n  isAntarcticaExpression := generateCheckAntarcticaExpression()\n  \/\/ \u5927\u6d32\u63cf\u8ff01\n  continentDescription1 := &quot;\u6b64\u5927\u6d32\u751f\u6d3b\u7740\u5927\u91cf\u4f01\u9e45\uff0c\u5168\u5e74\u4f4e\u6e29\uff0c\u5e76\u4e14\u4f34\u968f\u7740\u6709\u66b4\u98ce\u96ea&quot;\n  fmt.Printf(&quot;%s\uff0c\u662f\u5426\u662f\u5357\u6781\u6d32\uff1f%t\/n&quot;, continentDescription1, isAntarcticaExpression.Interpret(continentDescription1))\n  \/\/ \u5927\u6d32\u63cf\u8ff02\n  continentDescription2 := &quot;\u6b64\u5927\u6d32\u751f\u6d3b\u7740\u72ee\u5b50\uff0c\u5168\u5e74\u9ad8\u6e29\u591a\u96e8&quot;\n  fmt.Printf(&quot;%s\uff0c\u662f\u5426\u662f\u5357\u6781\u6d32\uff1f%t\/n&quot;, continentDescription2, isAntarcticaExpression.Interpret(continentDescription2))\n\n  isAmericanExpression := generateCheckAmericanExpression()\n  peopleDescription1 := &quot;\u6b64\u4eba\u751f\u6d3b\u5728\u5317\u7f8e\u6d32\u7684\u9ed1\u4eba\uff0c\u8bf4\u7740\u82f1\u8bed\uff0c\u6301\u6709\u7f8e\u56fd\u7eff\u5361&quot;\n  fmt.Printf(&quot;%s\uff0c\u662f\u5426\u662f\u7f8e\u56fd\u4eba\uff1f%t\/n&quot;, peopleDescription1, isAmericanExpression.Interpret(peopleDescription1))\n\n  peopleDescription2 := &quot;\u6b64\u4eba\u751f\u6d3b\u5728\u6b27\u6d32\uff0c\u8bf4\u7740\u82f1\u8bed\uff0c\u662f\u6b27\u6d32\u8bae\u4f1a\u8bae\u5458&quot;\n  fmt.Printf(&quot;%s\uff0c\u662f\u5426\u662f\u5357\u6781\u6d32\uff1f%t\/n&quot;, peopleDescription2, isAmericanExpression.Interpret(peopleDescription2))\n\n}\n\n\/\/ generateCheckAntarcticaExpression \u751f\u6210\u6821\u9a8c\u662f\u5426\u662f\u5357\u6781\u6d32\u8868\u8fbe\u5f0f\nfunc generateCheckAntarcticaExpression() Expression {\n  \/\/ \u5224\u65ad\u5357\u6781\u6d32\u7684\u52a8\u7269\uff0c\u6216\u5173\u7cfb\n  animalExpression := NewOrExpression(NewTerminalExpression(&quot;\u4f01\u9e45&quot;),\n    NewTerminalExpression(&quot;\u84dd\u9cb8&quot;))\n  \/\/ \u5224\u65ad\u5357\u6781\u6d32\u7684\u5929\u6c14\uff0c\u4e0e\u5173\u7cfb\n  weatherExpression := NewAndExpression(NewTerminalExpression(&quot;\u4f4e\u6e29&quot;),\n    NewTerminalExpression(&quot;\u66b4\u98ce\u96ea&quot;))\n  \/\/ \u6700\u7ec8\u8fd4\u56de\u52a8\u7269\u4e0e\u5929\u6c14\u7684\u4e0e\u5173\u7cfb\n  return NewAndExpression(animalExpression, weatherExpression)\n}\n\n\/\/ generateCheckAmericanExpression \u751f\u6210\u68c0\u67e5\u7f8e\u56fd\u4eba\u8868\u8fbe\u5f0f\nfunc generateCheckAmericanExpression() Expression {\n  \/\/ \u4eba\u79cd\u5224\u65ad\uff0c\u6216\u5173\u7cfb\n  raceExpression := NewOrExpression(NewTerminalExpression(&quot;\u767d\u4eba&quot;),\n    NewTerminalExpression(&quot;\u9ed1\u4eba&quot;))\n  \/\/ \u751f\u6d3b\u65b9\u5f0f\uff0c\u4e0e\u5173\u7cfb\n  lifeStyleExpression := NewAndExpression(NewTerminalExpression(&quot;\u82f1\u8bed&quot;),\n    NewTerminalExpression(&quot;\u5317\u7f8e\u6d32&quot;))\n  \/\/ \u8eab\u4efd\uff0c\u4e0e\u5173\u7cfb\n  identityExpression := NewAndExpression(lifeStyleExpression, NewTerminalExpression(&quot;\u7f8e\u56fd\u7eff\u5361&quot;))\n  return NewAndExpression(raceExpression, identityExpression)\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestInterpreter\n\u6b64\u5927\u6d32\u751f\u6d3b\u7740\u5927\u91cf\u4f01\u9e45\uff0c\u5168\u5e74\u4f4e\u6e29\uff0c\u5e76\u4e14\u4f34\u968f\u7740\u6709\u66b4\u98ce\u96ea\uff0c\u662f\u5426\u662f\u5357\u6781\u6d32\uff1ftrue\n\u6b64\u5927\u6d32\u751f\u6d3b\u7740\u72ee\u5b50\uff0c\u5168\u5e74\u9ad8\u6e29\u591a\u96e8\uff0c\u662f\u5426\u662f\u5357\u6781\u6d32\uff1ffalse\n\u6b64\u4eba\u751f\u6d3b\u5728\u5317\u7f8e\u6d32\u7684\u9ed1\u4eba\uff0c\u8bf4\u7740\u82f1\u8bed\uff0c\u6301\u6709\u7f8e\u56fd\u7eff\u5361\uff0c\u662f\u5426\u662f\u7f8e\u56fd\u4eba\uff1ftrue\n\u6b64\u4eba\u751f\u6d3b\u5728\u6b27\u6d32\uff0c\u8bf4\u7740\u82f1\u8bed\uff0c\u662f\u6b27\u6d32\u8bae\u4f1a\u8bae\u5458\uff0c\u662f\u5426\u662f\u7f8e\u56fd\u4eba\uff1ffalse\n--- PASS: TestInterpreter (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916588\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u9002\u914d\u5668\u6a21\u5f0f<\/strong><\/h2>\n<p><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong>  <\/p>\n<p>\u9002\u914d\u5668\u6a21\u5f0f\u662f\u4e00\u79cd\u7ed3\u6784\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5b83\u80fd\u4f7f\u63a5\u53e3\u4e0d\u517c\u5bb9\u7684\u5bf9\u8c61\u80fd\u591f\u76f8\u4e92\u5408\u4f5c\u3002<\/p>\n<p>\u9002\u914d\u5668\u53ef\u62c5\u4efb\u4e24\u4e2a\u5bf9\u8c61\u95f4\u7684\u5c01\u88c5\u5668\uff0c\u5b83\u4f1a\u63a5\u6536\u5bf9\u4e8e\u4e00\u4e2a\u5bf9\u8c61\u7684\u8c03\u7528\uff0c \u5e76\u5c06\u5176\u8f6c\u6362\u4e3a\u53e6\u4e00\u4e2a\u5bf9\u8c61\u53ef\u8bc6\u522b\u7684\u683c\u5f0f\u548c\u63a5\u53e3\u3002<\/p>\n<p><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong>  <\/p>\n<p>\u901a\u8fc7\u5145\u7535\u5b9d\u7ed9\u4e0d\u540c\u5145\u7535\u63a5\u53e3\u7684\u624b\u673a\u5145\u7535\u662f\u4e00\u4e2a\u975e\u5e38\u7b26\u5408\u9002\u914d\u5668\u6a21\u5f0f\u7279\u5f81\u7684\u751f\u6d3b\u793a\u4f8b\uff1b\u4e00\u822c\u5145\u7535\u5b9d\u63d0\u4f9bUSB\u7535\u6e90\u8f93\u51fa\u63a5\u53e3\uff0c\u624b\u673a\u5145\u7535\u8f93\u5165\u63a5\u53e3\u5219\u5206\u4e3a\u4e24\u7c7b\u4e00\u662f\u82f9\u679c\u624b\u673a\u7684lightning\u63a5\u53e3\uff0c\u53e6\u4e00\u7c7b\u662f\u5b89\u5353\u624b\u673a\u7684typeC\u63a5\u53e3\uff0c\u8fd9\u4e24\u7c7b\u63a5\u53e3\u90fd\u9700\u8981\u901a\u8fc7\u9002\u914d\u7535\u6e90\u7ebf\u8fde\u63a5\u5145\u7535\u5b9d\u7684USB\u63a5\u53e3\uff0c\u8fd9\u91ccUSB\u63a5\u53e3\u5c31\u76f8\u5f53\u4e8e\u5145\u7535\u5b9d\u7684\u901a\u7528\u63a5\u53e3\uff0clightning\u6216typeC\u63a5\u53e3\u8981\u60f3\u5145\u7535\u9700\u8981\u901a\u8fc7\u5145\u7535\u7ebf\u9002\u914d\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u624b\u673a\u5145\u7535\u63d2\u5934<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package adapter\n\nimport &quot;fmt&quot;\n\n\/\/ HuaweiPlug \u534e\u4e3a\u624b\u673a\u5145\u7535\u63d2\u69fd\u63a5\u53e3\ntype HuaweiPlug interface {\n  ConnectTypeC() string\n}\n\n\/\/ HuaweiPhone \u534e\u4e3a\u7cfb\u5217\u624b\u673a\ntype HuaweiPhone struct {\n  model string\n}\n\n\/\/ NewHuaweiPhone \u534e\u4e3a\u624b\u673a\u521b\u5efa\u65b9\u6cd5\nfunc NewHuaweiPhone(model string) *HuaweiPhone {\n  return &amp;HuaweiPhone{\n    model: model,\n  }\n}\n\n\/\/ ConnectTypeC \u534e\u4e3a\u624b\u673aTypeC\u5145\u7535\u63d2\u69fd\nfunc (h *HuaweiPhone) ConnectTypeC() string {\n  return fmt.Sprintf(&quot;%v connect typeC plug&quot;, h.model)\n}\n\n\/\/ ApplePlug \u82f9\u679c\u624b\u673a\u5145\u7535\u63d2\u69fd\ntype ApplePlug interface {\n  ConnectLightning() string\n}\n\n\/\/ IPhone \u82f9\u679c\u7cfb\u5217\u624b\u673a\ntype IPhone struct {\n  model string\n}\n\n\/\/ NewIPhone \u82f9\u679c\u624b\u673a\u521b\u5efa\u65b9\u6cd5\nfunc NewIPhone(model string) *IPhone {\n  return &amp;IPhone{\n    model: model,\n  }\n}\n\n\/\/ ConnectLightning \u82f9\u679c\u624b\u673aLightning\u5145\u7535\u63d2\u69fd\nfunc (i *IPhone) ConnectLightning() string {\n  return fmt.Sprintf(&quot;%v connect lightning plug&quot;, i.model)\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u5145\u7535\u5b9d\u9002\u914d\u5668<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package adapter\n\nimport &quot;fmt&quot;\n\n\n\/\/ CommonPlug \u901a\u7528\u7684USB\u7535\u6e90\u63d2\u69fd\ntype CommonPlug interface {\n  ConnectUSB() string\n}\n\n\/\/ HuaweiPhonePlugAdapter \u534e\u4e3aTypeC\u5145\u7535\u63d2\u69fd\u9002\u914d\u901a\u7528USB\u5145\u7535\u63d2\u69fd\ntype HuaweiPhonePlugAdapter struct {\n  huaweiPhone HuaweiPlug\n}\n\n\/\/ NewHuaweiPhonePlugAdapter \u521b\u5efa\u534e\u4e3a\u624b\u673a\u9002\u914dUSB\u5145\u7535\u63d2\u69fd\u9002\u914d\u5668\nfunc NewHuaweiPhonePlugAdapter(huaweiPhone HuaweiPlug) *HuaweiPhonePlugAdapter {\n  return &amp;HuaweiPhonePlugAdapter{\n    huaweiPhone: huaweiPhone,\n  }\n}\n\n\/\/ ConnectUSB \u94fe\u63a5USB\nfunc (h *HuaweiPhonePlugAdapter) ConnectUSB() string {\n  return fmt.Sprintf(&quot;%v adapt to usb &quot;, h.huaweiPhone.ConnectTypeC())\n}\n\n\/\/ ApplePhonePlugAdapter \u82f9\u679cLightning\u5145\u7535\u63d2\u69fd\u9002\u914d\u901a\u7528USB\u5145\u7535\u63d2\u69fd\ntype ApplePhonePlugAdapter struct {\n  iPhone ApplePlug\n}\n\n\/\/ NewApplePhonePlugAdapter \u521b\u5efa\u82f9\u679c\u624b\u673a\u9002\u914dUSB\u5145\u7535\u63d2\u69fd\u9002\u914d\u5668\nfunc NewApplePhonePlugAdapter(iPhone ApplePlug) *ApplePhonePlugAdapter {\n  return &amp;ApplePhonePlugAdapter{\n    iPhone: iPhone,\n  }\n}\n\n\/\/ ConnectUSB \u94fe\u63a5USB\nfunc (a *ApplePhonePlugAdapter) ConnectUSB() string {\n  return fmt.Sprintf(&quot;%v adapt to usb &quot;, a.iPhone.ConnectLightning())\n}\n\n\/\/ PowerBank \u5145\u7535\u5b9d\ntype PowerBank struct {\n  brand string\n}\n\n\/\/ Charge \u652f\u6301\u901a\u7528USB\u63a5\u53e3\u5145\u7535\nfunc (p *PowerBank) Charge(plug CommonPlug) string {\n  return fmt.Sprintf(&quot;%v power bank connect usb plug, start charge for %v&quot;, p.brand, plug.ConnectUSB())\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package adapter\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestAdapter (t *testing.T) {\n  huaweiMate40Pro := NewHuaweiPhone(&quot;\u534e\u4e3a mate40 pro&quot;)\n  iphone13MaxPro := NewIPhone(&quot;\u82f9\u679c iphone13 pro max&quot;)\n\n  powerBank := &amp;PowerBank{&quot;\u98de\u5229\u6d66&quot;}\n  fmt.Println(powerBank.Charge(NewHuaweiPhonePlugAdapter(huaweiMate40Pro)))\n  fmt.Println(powerBank.Charge(NewApplePhonePlugAdapter(iphone13MaxPro)))\n}<\/code><\/pre>\n<ul>\n<li><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/li>\n<\/ul>\n<pre><code>=== RUN   TestAdapter\n\u98de\u5229\u6d66 power bank connect usb plug, start charge for \u534e\u4e3a mate40 pro connect typeC plug adapt to usb \n\u98de\u5229\u6d66 power bank connect usb plug, start charge for \u82f9\u679c iphone13 pro max connect lightning plug adapt to usb \n--- PASS: TestAdapter (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916589\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u6865\u63a5\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u6865\u63a5\u662f\u4e00\u79cd\u7ed3\u6784\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u53ef\u5c06\u4e1a\u52a1\u903b\u8f91\u6216\u4e00\u4e2a\u5927\u7c7b\u62c6\u5206\u4e3a\u4e0d\u540c\u7684\u5c42\u6b21\u7ed3\u6784\uff0c \u4ece\u800c\u80fd\u72ec\u7acb\u5730\u8fdb\u884c\u5f00\u53d1\u3002<\/p>\n<p>\u5c42\u6b21\u7ed3\u6784\u4e2d\u7684\u7b2c\u4e00\u5c42\uff08\u901a\u5e38\u79f0\u4e3a\u62bd\u8c61\u90e8\u5206\uff09\u5c06\u5305\u542b\u5bf9\u7b2c\u4e8c\u5c42 \uff08\u5b9e\u73b0\u90e8\u5206\uff09 \u5bf9\u8c61\u7684\u5f15\u7528\u3002\u62bd\u8c61\u90e8\u5206\u5c06\u80fd\u5c06\u4e00\u4e9b\uff08\u6709\u65f6\u662f\u7edd\u5927\u90e8\u5206\uff09\u5bf9\u81ea\u5df1\u7684\u8c03\u7528\u59d4\u6d3e\u7ed9\u5b9e\u73b0\u90e8\u5206\u7684\u5bf9\u8c61\u3002\u6240\u6709\u7684\u5b9e\u73b0\u90e8\u5206\u90fd\u6709\u4e00\u4e2a\u901a\u7528\u63a5\u53e3\uff0c\u56e0\u6b64\u5b83\u4eec\u80fd\u5728\u62bd\u8c61\u90e8\u5206\u5185\u90e8\u76f8\u4e92\u66ff\u6362\u3002<\/p>\n<p>\u7b80\u5355\u7684\u8bf4\uff0c\u4e00\u4e2a\u4e8b\u7269\u5b58\u5728\u591a\u4e2a\u7ef4\u5ea6\u7684\u53d8\u5316\u70b9\uff0c\u6bcf\u4e00\u4e2a\u7ef4\u5ea6\u90fd\u62bd\u8c61\u51fa\u4e00\u4e2a\u63a5\u53e3\uff0c\u4e8b\u7269\u5f15\u7528\u8fd9\u4e9b\u63a5\u53e3\u5b9e\u73b0\u6574\u4f53\u884c\u4e3a\u903b\u8f91\uff0c\u800c\u6bcf\u4e00\u4e2a\u63a5\u53e3\u90fd\u53ef\u4ee5\u5b58\u5728\u591a\u4e2a\u53d8\u5316\u7684\u5b9e\u73b0\u3002<\/p>\n<p>\u66f4\u7b80\u5355\u7684\u4e00\u53e5\u8bdd\uff1a\u4f9d\u8d56\u63a5\u53e3\u7f16\u7a0b\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u5bf9\u4e8e\u4e00\u6bb5\u7ecf\u5386\u7684\u63cf\u8ff0\uff0c\u7ecf\u5386\u5c31\u53ef\u80fd\u6709\u591a\u79cd\u5b9e\u73b0\uff0c\u6bd4\u5982\u65c5\u6e38\u7ecf\u5386\uff0c\u63a2\u9669\u7ecf\u5386\u8fd9\u76f8\u5f53\u4e8e\u7b2c\u4e00\u5c42\u6b21\u7684\u7c7b\u7ed3\u6784\uff0c\u540c\u65f6\u63cf\u8ff0\u65c5\u6e38\u7ecf\u5386\u6216\u63a2\u9669\u7ecf\u5386\u53c8\u5305\u542b\u591a\u4e2a\u7ef4\u5ea6\uff0c\u6bd4\u5982\u5982\u4f55\u5230\u8fbe\u76ee\u7684\u5730\uff0c\u5728\u76ee\u7684\u5730\u5f00\u5c55\u4e86\u4ec0\u4e48\u6d3b\u52a8\u7b49\uff0c\u5230\u8fbe\u76ee\u7684\u5730\u6709\u5f88\u591a\u79cd\u65b9\u5f0f\uff0c\u6bd4\u5982\u98de\u673a\u3001\u706b\u8f66\u3001\u6c7d\u8f66\u7b49\uff1b\u5f00\u5c55\u7684\u6d3b\u52a8\u53c8\u6839\u636e\u5730\u70b9\u4e0d\u540c\u800c\u4e0d\u540c\uff0c\u6d77\u8fb9\u53ef\u4ee5\u51b2\u6d6a\uff0c\u5c71\u5730\u53ef\u4ee5\u6500\u5ca9\uff0c\u8352\u6f20\u53ef\u4ee5\u5f92\u6b65\u7a7f\u8d8a\u7b49\uff1b\u8fd9\u4e24\u4e2a\u7ef4\u5ea6\u7684\u53d8\u5316\u70b9\u5bf9\u4e8e\u63cf\u8ff0\u7ecf\u5386\u6765\u8bf4\u76f8\u5f53\u4e8e\u7b2c\u4e8c\u5c42\u6b21\u7c7b\u5b9e\u73b0\uff0c\u901a\u8fc7\u63a5\u53e3\u88ab\u7b2c\u4e00\u5c42\u6b21\u5f15\u7528\u3002<\/p>\n<p>\u8fd9\u91cc\u5bf9\u4e8e\u7ecf\u5386\u63cf\u8ff0\u5b58\u5728\u4e09\u4e2a\u7ef4\u5ea6\u7684\u53d8\u5316\uff0c<\/p>\n<p>1.\u7ecf\u5386\u672c\u8eab\u7684\u4e24\u4e2a\u5b9e\u73b0\uff1a\u65c5\u6e38\u7ecf\u5386\u4e0e\u63a2\u9669\u7ecf\u5386\u3002<\/p>\n<p>2.\u4ea4\u901a\u65b9\u5f0f\u7684\u4e24\u4e2a\u5b9e\u73b0\uff1a\u98de\u673a\u548c\u6c7d\u8f66\u3002<\/p>\n<p>3.\u5f00\u5c55\u6d3b\u52a8\u7684\u4e09\u4e2a\u5b9e\u73b0\uff1a\u51b2\u6d6a\u3001\u6500\u5ca9\u4e0e\u5f92\u6b65\u7a7f\u8d8a\u3002<\/p>\n<p>\u5982\u679c\u7528\u4e00\u4e2a\u7c7b\u5c42\u6b21\u53bb\u5b9e\u73b0\u5c31\u9700\u89812*2*3=12\u4e2a\u4e0d\u540c\u7684\u5b9e\u73b0\u7c7b\uff0c\u5982\u679c\u7528\u6865\u63a5\u6a21\u5f0f\u4ec5\u9700\u89812+2+3=7\u4e2a\u4e0d\u540c\u7684\u7c7b\uff0c\u800c\u4e14\u4e24\u79cd\u65b9\u5f0f\u7684\u52a0\u901f\u5ea6\u4e5f\u4e0d\u4e00\u6837\uff0c\u6bd4\u5982\u589e\u52a0\u4e00\u4e2a\u4ea4\u901a\u65b9\u5f0f\u706b\u8f66\uff0c\u975e\u6865\u63a5\u6a21\u5f0f\u9700\u8981\u589e\u52a02*3*3-12=6\u4e2a\u5b9e\u73b0\u7c7b\uff0c\u6865\u63a5\u6a21\u5f0f2+3+3-7=1\u4e2a\u5b9e\u73b0\u7c7b\uff1b\u6865\u63a5\u6a21\u5f0f\u5927\u5927\u589e\u52a0\u4e86\u7c7b\u4e4b\u95f4\u7ec4\u5408\u7684\u7075\u6d3b\u6027\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u4ea4\u901a\u5de5\u5177<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package bridge\n\n\/\/ Traffic \u4ea4\u901a\u5de5\u5177\ntype Traffic interface {\n   Transport() string\n}\n\n\/\/ airplane \u98de\u673a\ntype airplane struct{}\n\n\/\/ Transport \u5750\u98de\u673a\nfunc (a *airplane) Transport() string {\n   return &quot;by airplane&quot;\n}\n\n\/\/ car \u6c7d\u8f66\ntype car struct{}\n\n\/\/ Transport \u5750\u6c7d\u8f66\nfunc (t *car) Transport() string {\n   return &quot;by car&quot;\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u76ee\u7684\u5730<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package bridge\n\nimport &quot;fmt&quot;\n\n\/\/ Location \u5730\u70b9\ntype Location interface {\n  Name() string \/\/ \u5730\u70b9\u540d\u79f0\n  PlaySports() string \/\/ \u53c2\u4e0e\u8fd0\u52a8\n}\n\n\/\/ namedLocation \u88ab\u547d\u540d\u7684\u5730\u70b9\uff0c\u7edf\u4e00\u5f15\u7528\u6b64\u7c7b\u578b\uff0c\u58f0\u660e\u540d\u5b57\u5b57\u6bb5\u53ca\u83b7\u53d6\u65b9\u6cd5\ntype namedLocation struct {\n  name string\n}\n\n\/\/ Name \u83b7\u53d6\u5730\u70b9\u540d\u79f0\nfunc (n namedLocation) Name() string {\n  return n.name\n}\n\n\/\/ seaside \u6d77\u8fb9\ntype seaside struct {\n  namedLocation\n}\n\n\/\/ NewSeaside \u521b\u5efa\u6307\u5b9a\u540d\u5b57\u7684\u6d77\u8fb9\uff0c\u6bd4\u5982\u4e09\u4e9a\u6e7e\nfunc NewSeaside(name string) *seaside {\n  return &amp;seaside{\n    namedLocation: namedLocation{\n      name: name,\n    },\n  }\n}\n\n\/\/ PlaySports \u6d77\u8fb9\u53ef\u4ee5\u51b2\u6d6a\nfunc (s *seaside) PlaySports() string {\n  return fmt.Sprintf(&quot;surfing&quot;)\n}\n\n\/\/ mountain \u5c71\ntype mountain struct {\n  namedLocation\n}\n\n\/\/ NewMountain \u521b\u5efa\u6307\u5b9a\u540d\u5b57\u7684\u5c71\uff0c\u6bd4\u5982\u6cf0\u5c71\nfunc NewMountain(name string) *mountain {\n  return &amp;mountain{\n    namedLocation: namedLocation{\n      name: name,\n    },\n  }\n}\n\n\/\/ PlaySports \u53ef\u4ee5\u722c\u5c71\nfunc (m *mountain) PlaySports() string {\n  return fmt.Sprintf(&quot;climbing&quot;)\n}\n\n\/\/ desert \u8352\u6f20\ntype desert struct {\n  namedLocation\n}\n\n\/\/ NewDesert \u521b\u5efa\u6307\u5b9a\u540d\u5b57\u7684\u8352\u6f20\uff0c\u6bd4\u5982\u7f57\u5e03\u6cca\nfunc NewDesert(name string) *desert {\n  return &amp;desert{\n    namedLocation: namedLocation{\n      name: name,\n    },\n  }\n}\n\n\/\/ PlaySports \u8352\u6f20\u53ef\u4ee5\u5f92\u6b65\u7a7f\u8d8a\nfunc (d *desert) PlaySports() string {\n  return fmt.Sprintf(&quot;trekking&quot;)\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u7ecf\u5386\u63cf\u8ff0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package bridge\n\nimport &quot;fmt&quot;\n\n\/\/ Experience \u7ecf\u5386\ntype Experience interface {\n  Describe() string \/\/ \u63cf\u8ff0\u7ecf\u5386\n}\n\n\/\/ travelExperience \u65c5\u6e38\u7ecf\u5386\ntype travelExperience struct {\n  subject  string\n  traffic  Traffic\n  location Location\n}\n\n\/\/ NewTravelExperience \u521b\u5efa\u65c5\u6e38\u7ecf\u5386\uff0c\u5305\u62ec\u4e3b\u9898\u3001\u4ea4\u901a\u65b9\u5f0f\u3001\u5730\u70b9\nfunc NewTravelExperience(subject string, traffic Traffic, location Location) *travelExperience {\n  return &amp;travelExperience{\n    subject:  subject,\n    traffic:  traffic,\n    location: location,\n  }\n}\n\n\/\/ Describe \u63cf\u8ff0\u65c5\u6e38\u7ecf\u5386\nfunc (t *travelExperience) Describe() string {\n  return fmt.Sprintf(&quot;%s is to %s %s and %s&quot;, t.subject, t.location.Name(), t.traffic.Transport(), t.location.PlaySports())\n}\n\n\/\/ adventureExperience \u63a2\u9669\u7ecf\u5386\ntype adventureExperience struct {\n  survivalTraining string\n  travelExperience\n}\n\n\/\/ NewAdventureExperience \u521b\u5efa\u63a2\u9669\u7ecf\u5386\uff0c\u5305\u62ec\u63a2\u9669\u9700\u8981\u7684\u57f9\u8bad\uff0c\u5176\u4ed6\u7684\u4e0e\u8def\u7531\u53c2\u6570\u7c7b\u4f3c\nfunc NewAdventureExperience(training string, subject string, traffic Traffic, location Location) *adventureExperience {\n  return &amp;adventureExperience{\n    survivalTraining: training,\n    travelExperience: *NewTravelExperience(subject, traffic, location),\n  }\n}\n\n\/\/ Describe \u63cf\u8ff0\u63a2\u9669\u7ecf\u5386\nfunc (a *adventureExperience) Describe() string {\n  return fmt.Sprintf(&quot;after %s, %s&quot;, a.survivalTraining, a.travelExperience.Describe())\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package bridge\n\nimport (\n   &quot;fmt&quot;\n   &quot;testing&quot;\n)\n\nfunc TestBridge(t *testing.T) {\n   \/\/ \u5750\u98de\u673a\u53bb\u4e09\u4e9a\u5ea6\u871c\u6708\n   honeymoonTravel := NewTravelExperience(&quot;honeymoon&quot;, new(airplane), NewSeaside(&quot;SanyaYalongBay&quot;))\n   fmt.Println(honeymoonTravel.Describe())\n   \/\/ \u5750\u8f66\u53bb\u6cf0\u5c71\u6bd5\u4e1a\u65c5\u6e38\n   graduationTrip := NewTravelExperience(&quot;graduationTrip&quot;, new(car), NewMountain(&quot;Tarzan&quot;))\n   fmt.Println(graduationTrip.Describe())\n\n   \/\/ \u91ce\u5916\u751f\u5b58\u57f9\u8bad\u540e\uff0c\u5750\u8f66\u53bb\u7f57\u5e03\u6cca\uff0c\u5f92\u6b65\u7a7f\u8d8a\n   desertAdventure := NewAdventureExperience(&quot;wilderness survival training&quot;, &quot;adventure&quot;, new(car), NewDesert(&quot;Lop Nor&quot;))\n   fmt.Println(desertAdventure.Describe())\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestBridge\nhoneymoon is to SanyaYalongBay by airplane and surfing\ngraduationTrip is to Tarzan by car and climbing\nafter wilderness survival training, adventure is to Lop Nor by car and trekking\n--- PASS: TestBridge (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916590\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u7ec4\u5408\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u7ec4\u5408\u662f\u4e00\u79cd\u7ed3\u6784\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528\u5b83\u5c06\u5bf9\u8c61\u7ec4\u5408\u6210\u6811\u72b6\u7ed3\u6784\uff0c\u5e76\u4e14\u80fd\u50cf\u4f7f\u7528\u72ec\u7acb\u5bf9\u8c61\u4e00\u6837\u4f7f\u7528\u5b83\u4eec\u3002<\/p>\n<p>\u5bf9\u4e8e\u7edd\u5927\u591a\u6570\u9700\u8981\u751f\u6210\u6811\u72b6\u7ed3\u6784\u7684\u95ee\u9898\u6765\u8bf4\uff0c\u7ec4\u5408\u90fd\u662f\u975e\u5e38\u53d7\u6b22\u8fce\u7684\u89e3\u51b3\u65b9\u6848\u3002\u7ec4\u5408\u6700\u4e3b\u8981\u7684\u529f\u80fd\u662f\u5728\u6574\u4e2a\u6811\u72b6\u7ed3\u6784\u4e0a\u9012\u5f52\u8c03\u7528\u65b9\u6cd5\u5e76\u5bf9\u7ed3\u679c\u8fdb\u884c\u6c47\u603b\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u4e00\u822c\u6765\u8bf4\u4e00\u4e2a\u5730\u533a\u7edf\u8ba1\u4eba\u53e3\u6216\u7ecf\u6d4e\u603b\u91cf\uff0c\u603b\u662f\u901a\u8fc7\u884c\u653f\u533a\u5212\u4e00\u5c42\u5c42\u4e0a\u62a5\u6c47\u603b\u5f97\u51fa\u7ed3\u679c\uff0c\u533a\u9547\u662f\u6700\u4f4e\u4e00\u7ea7\u884c\u653f\u533a\u5212\uff0c\u9700\u8981\u843d\u5b9e\u7edf\u8ba1\u4eba\u53e3\u53ca\u7ecf\u6d4e\u603b\u91cf\u7684\u5de5\u4f5c\uff0c\u518d\u4e0a\u4e00\u7ea7\u884c\u653f\u533a\u5212\u9700\u8981\u5c06\u6240\u8f96\u533a\u9547\u7684\u6570\u636e\u6c47\u603b\u7edf\u8ba1\uff0c\u4ee5\u6b64\u7c7b\u63a8\u6bcf\u4e00\u7ea7\u884c\u653f\u533a\u5212\u90fd\u9700\u8981\u7edf\u8ba1\u4eba\u53e3\u4e0e\u7ecf\u6d4e\u603b\u91cf\uff0c\u5c31\u50cf\u4e00\u4e2a\u5012\u8fc7\u6765\u7684\u6811\u72b6\u7ed3\u6784\uff0c\u5404\u7ea7\u884c\u653f\u533a\u5212\u7edf\u4e00\u7684\u7ec4\u4ef6\u63a5\u53e3\u662f\u7edf\u8ba1\u4eba\u53e3\u4e0e\u7ecf\u6d4e\u603b\u91cf\uff0c\u533a\u9547\u76f8\u5f53\u4e8e\u6700\u5e95\u5c42\u7684\u53f6\u5b50\u8282\u70b9\uff0c\u4e2d\u95f4\u7ea7\u522b\u884c\u653f\u533a\u5212\u76f8\u5f53\u4e8e\u7ec4\u5408\u8282\u70b9\uff1b\u4e0b\u9762\u4ee3\u7801\u4ee5\u82cf\u5dde\u5e02\u4e3a\u4f8b\uff1b<\/p>\n<ul>\n<li>\n<h4><strong>\u7ec4\u4ef6\u63a5\u53e3<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package composite\n\n\/\/ Region \u884c\u653f\u533a\uff0c\u4f5c\u4e3a\u7ec4\u5408\u6a21\u5f0fcomponent\u63a5\u53e3\ntype Region interface {\n   Name() string    \/\/ \u540d\u79f0\n   Population() int \/\/\u4eba\u53e3\n   GDP() float64    \/\/ gdp\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u533a\u9547\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package composite\n\n\/\/ town \u533a\u9547\uff0c\u7ec4\u5408\u6a21\u5f0f\u4e2d\u76f8\u5f53\u4e8e\u53f6\u5b50\u8282\u70b9\ntype town struct {\n  name       string\n  population int\n  gdp        float64\n}\n\n\/\/ NewTown \u521b\u5efa\u533a\u9547\uff0c\u6839\u636e\u540d\u79f0\u3001\u4eba\u53e3\u3001GDP\nfunc NewTown(name string, population int, gdp float64) *town {\n  return &amp;town{\n    name:       name,\n    population: population,\n    gdp:        gdp,\n  }\n}\n\nfunc (c *town) Name() string {\n  return c.name\n}\n\nfunc (c *town) Population() int {\n  return c.population\n}\n\nfunc (c *town) GDP() float64 {\n  return c.gdp\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u53bf\u5e02\u5730\u5e02\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package composite\n\n\/\/ cities \u5e02\uff0c\u5305\u62ec\u53bf\u5e02\u6216\u8005\u5730\u5e02\uff0c\u7ec4\u5408\u6a21\u5f0f\u4e2d\u76f8\u5f53\u4e8ecomposite\ntype cities struct {\n  name    string\n  regions map[string]Region\n}\n\n\/\/ NewCities \u521b\u5efa\u4e00\u4e2a\u5e02\nfunc NewCities(name string) *cities {\n  return &amp;cities{\n    name:    name,\n    regions: make(map[string]Region),\n  }\n}\n\nfunc (c *cities) Name() string {\n  return c.name\n}\n\nfunc (c *cities) Population() int {\n  sum := 0\n  for _, r := range c.regions {\n    sum += r.Population()\n  }\n  return sum\n}\n\nfunc (c *cities) GDP() float64 {\n  sum := 0.0\n  for _, r := range c.regions {\n    sum += r.GDP()\n  }\n  return sum\n}\n\n\/\/ Add \u6dfb\u52a0\u591a\u4e2a\u884c\u653f\u533a\nfunc (c *cities) Add(regions ...Region) {\n  for _, r := range regions {\n    c.regions[r.Name()] = r\n  }\n}\n\n\/\/ Remove \u9012\u5f52\u5220\u9664\u884c\u653f\u533a\nfunc (c *cities) Remove(name string) {\n  for n, r := range c.regions {\n    if n == name {\n      delete(c.regions, name)\n      return\n    }\n    if city, ok := r.(*cities); ok {\n      city.Remove(name)\n    }\n  }\n}\n\nfunc (c *cities) Regions() map[string]Region {\n  return c.regions\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package composite\n\nimport (\n   &quot;fmt&quot;\n   &quot;testing&quot;\n)\n\nfunc TestComposite(t *testing.T) {\n   gusu := NewTown(&quot;\u59d1\u82cf\u533a&quot;, 100, 2000.00)\n   fmt.Println(ShowRegionInfo(gusu))\n   wuzhong := NewTown(&quot;\u5434\u4e2d\u533a&quot;, 150, 2600.00)\n   fmt.Println(ShowRegionInfo(wuzhong))\n   huqiu := NewTown(&quot;\u864e\u4e18\u533a&quot;, 80, 1800.00)\n   fmt.Println(ShowRegionInfo(huqiu))\n\n   kunshan := NewCities(&quot;\u6606\u5c71\u5e02&quot;)\n   kunshan.Add(NewTown(&quot;\u7389\u5c71\u9547&quot;, 60, 1200.00),\n      NewTown(&quot;\u5468\u5e84\u9547&quot;, 68, 1900.00),\n      NewTown(&quot;\u82b1\u6865\u9547&quot;, 78, 2200.00))\n   fmt.Println(ShowRegionInfo(kunshan))\n\n   changshu := NewCities(&quot;\u5e38\u719f\u5e02&quot;)\n   changshu.Add(NewTown(&quot;\u6c99\u5bb6\u6d5c\u9547&quot;, 55, 1100.00),\n      NewTown(&quot;\u53e4\u91cc\u9547&quot;, 59, 1300.00),\n      NewTown(&quot;\u8f9b\u5e84\u9547&quot;, 68, 2100.00))\n   fmt.Println(ShowRegionInfo(changshu))\n\n   suzhou := NewCities(&quot;\u82cf\u5dde\u5e02&quot;)\n   suzhou.Add(gusu, wuzhong, huqiu, kunshan, changshu)\n   fmt.Println(ShowRegionInfo(suzhou))\n\n}\n\nfunc ShowRegionInfo(region Region) string {\n   return fmt.Sprintf(&quot;%s, \u4eba\u53e3:%d\u4e07, GDP:%.2f\u4ebf&quot;, region.Name(), region.Population(), region.GDP())\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestComposite\n\u59d1\u82cf\u533a, \u4eba\u53e3:100\u4e07, GDP:2000.00\u4ebf\n\u5434\u4e2d\u533a, \u4eba\u53e3:150\u4e07, GDP:2600.00\u4ebf\n\u864e\u4e18\u533a, \u4eba\u53e3:80\u4e07, GDP:1800.00\u4ebf\n\u6606\u5c71\u5e02, \u4eba\u53e3:206\u4e07, GDP:5300.00\u4ebf\n\u5e38\u719f\u5e02, \u4eba\u53e3:182\u4e07, GDP:4500.00\u4ebf\n\u82cf\u5dde\u5e02, \u4eba\u53e3:718\u4e07, GDP:16200.00\u4ebf\n--- PASS: TestComposite (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916591\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u88c5\u9970\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u88c5\u9970\u662f\u4e00\u79cd\u7ed3\u6784\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5141\u8bb8\u4f60\u901a\u8fc7\u5c06\u5bf9\u8c61\u653e\u5165\u7279\u6b8a\u5c01\u88c5\u5bf9\u8c61\u4e2d\u6765\u4e3a\u539f\u5bf9\u8c61\u589e\u52a0\u65b0\u7684\u884c\u4e3a\u3002<\/p>\n<p>\u7531\u4e8e\u76ee\u6807\u5bf9\u8c61\u548c\u88c5\u9970\u5668\u9075\u5faa\u540c\u4e00\u63a5\u53e3\uff0c\u56e0\u6b64\u4f60\u53ef\u7528\u88c5\u9970\u6765\u5bf9\u5bf9\u8c61\u8fdb\u884c\u65e0\u9650\u6b21\u7684\u5c01\u88c5\u3002\u7ed3\u679c\u5bf9\u8c61\u5c06\u83b7\u5f97\u6240\u6709\u5c01\u88c5\u5668\u53e0\u52a0\u800c\u6765\u7684\u884c\u4e3a\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u5730\u94c1\u8fdb\u7ad9\u7684\u8fc7\u7a0b\u4e00\u822c\u60c5\u51b5\u4e0b\u53ea\u9700\u8981\u4e70\u7968\uff0c\u68c0\u7968\u8fdb\u7ad9\uff0c\u4f46\u662f\u5982\u679c\u4f60\u662f\u5e26\u884c\u674e\uff0c\u5c31\u9700\u8981\u8fdb\u884c\u5b89\u5168\u68c0\u67e5\uff0c\u5982\u679c\u662f\u75ab\u60c5\u65f6\u671f\uff0c\u5c31\u9700\u8981\u8fdb\u884c\u75ab\u60c5\u9632\u62a4\u68c0\u67e5\uff0c\u6bd4\u5982\u6234\u53e3\u7f69\u3001\u6d4b\u91cf\u4f53\u6e29\u7b49\uff0c\u8fd9\u91cc\u4e70\u7968\u8fdb\u7ad9\u76f8\u5f53\u4e8e\u901a\u7528\u8fdb\u7ad9\u6d41\u7a0b\uff0c\u5b89\u68c0\u53ca\u9632\u75ab\u68c0\u67e5\u5c31\u76f8\u5f53\u4e8e\u52a0\u5f3a\u7684\u4fee\u9970\u884c\u4e3a\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u4fee\u9970\u5668\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package decorator\n\nimport &quot;fmt&quot;\n\n\/\/ Station \u8f66\u7ad9\uff0c\u4fee\u9970\u5668\u6a21\u5f0f\u7edf\u4e00\u63a5\u53e3\ntype Station interface {\n  Enter() string \/\/ \u8fdb\u7ad9\n}\n\n\/\/ subwayStation \u5730\u94c1\u7ad9\ntype subwayStation struct {\n  name string\n}\n\n\/\/ NewSubwayStation \u521b\u5efa\u6307\u5b9a\u7ad9\u540d\u5730\u94c1\u7ad9\nfunc NewSubwayStation(name string) *subwayStation {\n  return &amp;subwayStation{\n    name: name,\n  }\n}\n\n\/\/ Enter \u8fdb\u5730\u94c1\u7ad9\nfunc (s *subwayStation) Enter() string {\n  return fmt.Sprintf(&quot;\u4e70\u7968\u8fdb\u5165%s\u5730\u94c1\u7ad9\u3002&quot;, s.name)\n}\n\n\/\/ securityCheckDecorator \u8fdb\u7ad9\u5b89\u68c0\u4fee\u9970\u5668\ntype securityCheckDecorator struct {\n  station Station\n}\n\nfunc NewSecurityCheckDecorator(station Station) *securityCheckDecorator {\n  return &amp;securityCheckDecorator{\n    station: station,\n  }\n}\n\nfunc (s *securityCheckDecorator) Enter() string {\n  return &quot;\u884c\u674e\u901a\u8fc7\u5b89\u68c0\uff1b&quot; + s.station.Enter()\n}\n\n\/\/ epidemicProtectionDecorator \u8fdb\u7ad9\u75ab\u60c5\u9632\u62a4\u4fee\u9970\u5668\ntype epidemicProtectionDecorator struct {\n  station Station\n}\n\nfunc NewEpidemicProtectionDecorator(station Station) *epidemicProtectionDecorator {\n  return &amp;epidemicProtectionDecorator{\n    station: station,\n  }\n}\n\nfunc (e *epidemicProtectionDecorator) Enter() string {\n  return &quot;\u6d4b\u91cf\u4f53\u6e29\uff0c\u4f69\u6234\u53e3\u7f69\uff1b&quot; + e.station.Enter()\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u4ee3\u7801<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package decorator\n\nimport (\n   &quot;fmt&quot;\n   &quot;testing&quot;\n)\n\nfunc TestDecorator(t *testing.T) {\n   xierqiStation := NewSubwayStation(&quot;\u897f\u4e8c\u65d7&quot;)\n   fmt.Println(EnhanceEnterStationProcess(xierqiStation, false, false).Enter())\n   fmt.Println(EnhanceEnterStationProcess(xierqiStation, true, false).Enter())\n   fmt.Println(EnhanceEnterStationProcess(xierqiStation, true, true).Enter())\n}\n\n\/\/ EnhanceEnterStationProcess \u6839\u636e\u662f\u5426\u6709\u884c\u674e\uff0c\u662f\u5426\u5904\u4e8e\u75ab\u60c5\uff0c\u589e\u52a0\u8fdb\u7ad9\u6d41\u7a0b\nfunc EnhanceEnterStationProcess(station Station, hasLuggage bool, hasEpidemic bool) Station {\n   if hasLuggage {\n      station = NewSecurityCheckDecorator(station)\n   }\n   if hasEpidemic {\n      station = NewEpidemicProtectionDecorator(station)\n   }\n   return station\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestDecorator\n\u4e70\u7968\u8fdb\u5165\u897f\u4e8c\u65d7\u5730\u94c1\u7ad9\u3002\n\u884c\u674e\u901a\u8fc7\u5b89\u68c0\uff1b\u4e70\u7968\u8fdb\u5165\u897f\u4e8c\u65d7\u5730\u94c1\u7ad9\u3002\n\u6d4b\u91cf\u4f53\u6e29\uff0c\u4f69\u6234\u53e3\u7f69\uff1b\u884c\u674e\u901a\u8fc7\u5b89\u68c0\uff1b\u4e70\u7968\u8fdb\u5165\u897f\u4e8c\u65d7\u5730\u94c1\u7ad9\u3002\n--- PASS: TestDecorator (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916592\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u5916\u89c2\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u5916\u89c2\u662f\u4e00\u79cd\u7ed3\u6784\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u80fd\u4e3a\u590d\u6742\u7cfb\u7edf\u3001\u7a0b\u5e8f\u5e93\u6216\u6846\u67b6\u63d0\u4f9b\u4e00\u4e2a\u7b80\u5355 \uff08\u4f46\u6709\u9650\uff09 \u7684\u63a5\u53e3\u3002<\/p>\n<p>\u5c3d\u7ba1\u5916\u89c2\u6a21\u5f0f\u964d\u4f4e\u4e86\u7a0b\u5e8f\u7684\u6574\u4f53\u590d\u6742\u5ea6\uff0c\u4f46\u5b83\u540c\u65f6\u4e5f\u6709\u52a9\u4e8e\u5c06\u4e0d\u9700\u8981\u7684\u4f9d\u8d56\u79fb\u52a8\u5230\u540c\u4e00\u4e2a\u4f4d\u7f6e\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u7528\u6237\u5728\u6dd8\u5b9d\u7535\u5546\u7cfb\u7edf\u4e70\u5546\u54c1\u65f6\uff0c\u53ea\u9700\u8981\u9009\u597d\u5546\u54c1\u5728\u7ed3\u7b97\u9875\u70b9\u51fb\u63d0\u4ea4\u5373\u53ef\u5b8c\u6210\u4e0b\u5355\uff1b\u5728\u5ba2\u6237\u7aef\u7cfb\u7edf\u4ec5\u9700\u8981\u4e00\u4e2a\u521b\u5efa\u8ba2\u5355\u7684\u65b9\u6cd5\uff0c\u4f46\u662f\u6574\u4e2a\u8ba2\u5355\u7684\u751f\u6210\u9700\u8981\u5f88\u591a\u6b65\u9aa4\uff0c\u6bd4\u5982\u67e5\u8be2\u7528\u6237\u914d\u9001\u5730\u5740\uff0c\u67e5\u8be2\u5546\u54c1\u4ef7\u683c\uff0c\u4f7f\u7528\u4f18\u60e0\u5238\uff0c\u6263\u51cf\u5546\u54c1\u5e93\u5b58\uff0c\u652f\u4ed8\u76f8\u5e94\u4ef7\u94b1\u7b49\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u6dd8\u5b9d\u7535\u5546\u7cfb\u7edf<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package facade\n\nimport &quot;fmt&quot;\n\n\/\/ TaobaoFacade \u6dd8\u5b9d\u7f51\u7ad9\u95e8\u9762\uff0c\u5728\u6dd8\u5b9d\u7f51\u7ad9\u4e0b\u5355\u6d89\u53ca\u5230\u591a\u4e2a\u7cfb\u7edf\u914d\u5408\u8c03\u7528\uff0c\u5305\u62ec\u7528\u6237\u7cfb\u7edf\uff0c\u5546\u54c1\u7cfb\u7edf\uff0c\u4f18\u60e0\u5238\u7cfb\u7edf\uff0c\u5e93\u5b58\u7cfb\u7edf\uff0c\u652f\u4ed8\u7cfb\u7edf\uff0c\u6700\u7ec8\u751f\u6210\u8ba2\u5355\ntype TaobaoFacade struct {\n  userService    *UserService\n  productService *ProductService\n  couponService  *CouponService\n  stockService   *StockService\n  paymentService *PaymentService\n}\n\n\/\/ NewTaobaoFacade \u521b\u5efa\u6dd8\u5b9d\u7f51\u7ad9\nfunc NewTaobaoFacade() *TaobaoFacade {\n  return &amp;TaobaoFacade{\n    userService: &amp;UserService{},\n    productService: &amp;ProductService{\n      products: map[string]float64{&quot;\u7b14\u8bb0\u672c\u7535\u8111&quot;: 6666.66},\n    },\n    couponService:  &amp;CouponService{},\n    stockService:   &amp;StockService{},\n    paymentService: &amp;PaymentService{},\n  }\n}\n\n\/\/ CreateOrder \u6839\u636e\u7528\u6237\u540d\uff0c\u5546\u54c1\u540d\uff0c\u5546\u54c1\u6570\u91cf\u751f\u6210\u8d2d\u4e70\u8ba2\u5355\nfunc (t *TaobaoFacade) CreateOrder(userName string, productName string, count int) string {\n  \/\/ \u4f7f\u7528\u4f18\u60e0\u5238\n  couponInfo := t.couponService.useCoupon()\n  \/\/ \u6263\u51cf\u5e93\u5b58\n  stockInfo := t.stockService.decreaseFor(productName, count)\n  \/\/ \u8ba1\u7b97\u5546\u54c1\u603b\u4ef7\n  sumPrice := t.productService.getProductPrice(productName) * float64(count)\n  \/\/ \u652f\u4ed8\u4ef7\u683c\n  payInfo := t.paymentService.pay(sumPrice)\n  return fmt.Sprintf(&quot;\u7528\u6237%s,\u8d2d\u4e70\u4e86%d\u4ef6%s\u5546\u54c1,%s,%s,%s,\u9001\u8d27\u5230%s&quot;, userName, count, productName, couponInfo,\n    stockInfo, payInfo, t.userService.getUserAddress(userName))\n}\n\n\/\/ UserService \u7528\u6237\u7cfb\u7edf\ntype UserService struct{}\n\nfunc (u *UserService) getUserAddress(userName string) string {\n  return fmt.Sprintf(&quot;%s\u5730\u5740\u662f:\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u4e2d\u5173\u6751\u5927\u8857\uff0c1\u53f7\u96622\u53f7\u697c3\u5355\u5143402&quot;, userName)\n}\n\n\/\/ ProductService \u5546\u54c1\u7cfb\u7edf\ntype ProductService struct {\n  products map[string]float64\n}\n\nfunc (p *ProductService) getProductPrice(productName string) float64 {\n  return p.products[productName]\n}\n\n\/\/ CouponService \u4f18\u60e0\u5238\u7cfb\u7edf\ntype CouponService struct{}\n\nfunc (c *CouponService) useCoupon() string {\n  return &quot;\u4f7f\u7528\u6ee1100\u51cf20\u4f18\u60e0\u5238&quot;\n}\n\n\/\/ StockService \u5e93\u5b58\u7cfb\u7edf\ntype StockService struct{}\n\nfunc (s *StockService) decreaseFor(productName string, count int) string {\n  return fmt.Sprintf(&quot;\u6263\u51cf%d\u4ef6%s\u5546\u54c1\u5e93\u5b58&quot;, count, productName)\n}\n\n\/\/ PaymentService \u652f\u4ed8\u7cfb\u7edf\ntype PaymentService struct{}\n\nfunc (p *PaymentService) pay(amount float64) string {\n  return fmt.Sprintf(&quot;\u652f\u4ed8\u91d1\u989d%.2f&quot;, amount)\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package facade\n\nimport (\n   &quot;fmt&quot;\n   &quot;testing&quot;\n)\n\nfunc TestFacade(t *testing.T) {\n   \/\/ \u901a\u8fc7\u95e8\u9762\u6a21\u5f0f\uff0c\u9690\u85cf\u4e0b\u5355\u8fc7\u7a0b\u4e2d\uff0c\u540e\u7aef\u591a\u4e2a\u7cfb\u7edf\u7684\u590d\u6742\u4ea4\u4e92\n   taobao := NewTaobaoFacade()\n   fmt.Println(taobao.CreateOrder(&quot;\u5f20\u4e09&quot;, &quot;\u7b14\u8bb0\u672c\u7535\u8111&quot;, 1))\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestFacade\n\u7528\u6237\u5f20\u4e09,\u8d2d\u4e70\u4e861\u4ef6\u7b14\u8bb0\u672c\u7535\u8111\u5546\u54c1,\u4f7f\u7528\u6ee1100\u51cf20\u4f18\u60e0\u5238,\u6263\u51cf1\u4ef6\u7b14\u8bb0\u672c\u7535\u8111\u5546\u54c1\u5e93\u5b58,\u652f\u4ed8\u91d1\u989d6666.66,\u9001\u8d27\u5230\u5f20\u4e09\u5730\u5740\u662f:\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u4e2d\u5173\u6751\u5927\u8857\uff0c1\u53f7\u96622\u53f7\u697c3\u5355\u5143402\n--- PASS: TestFacade (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916593\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u4eab\u5143\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u4eab\u5143\u662f\u4e00\u79cd\u7ed3\u6784\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5b83\u5141\u8bb8\u4f60\u5728\u6d88\u8017\u5c11\u91cf\u5185\u5b58\u7684\u60c5\u51b5\u4e0b\u652f\u6301\u5927\u91cf\u5bf9\u8c61\u3002<\/p>\n<p>\u6a21\u5f0f\u901a\u8fc7\u5171\u4eab\u591a\u4e2a\u5bf9\u8c61\u7684\u90e8\u5206\u72b6\u6001\u6765\u5b9e\u73b0\u4e0a\u8ff0\u529f\u80fd\u3002\u6362\u53e5\u8bdd\u6765\u8bf4\uff0c\u4eab\u5143\u4f1a\u5c06\u4e0d\u540c\u5bf9\u8c61\u7684\u76f8\u540c\u6570\u636e\u8fdb\u884c\u7f13\u5b58\u4ee5\u8282\u7701\u5185\u5b58\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u5317\u4eac\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf\uff0c\u9700\u8981\u6bcf\u9694\u4e00\u5206\u949f\u8bb0\u5f55\u4e00\u4e0b\u5168\u5e02\u51fa\u79df\u8f66\u7684\u4f4d\u7f6e\u4fe1\u606f\uff0c\u5047\u8bbe\u4e3a\u4e86\u63d0\u9ad8\u7cfb\u7edf\u54cd\u5e94\u901f\u5ea6\uff0c\u8fd1\u4e00\u5929\u7684\u6570\u636e\u9700\u8981\u5b58\u50a8\u5728\u5185\u5b58\u4e2d\uff0c\u6bcf\u4e2a\u4f4d\u7f6e\u4fe1\u606f\u5305\u62ec\u51fa\u79df\u8f66\u8f86\u4fe1\u606f\u53ca\u4f4d\u7f6e\u4fe1\u606f\uff0c\u4f4d\u7f6e\u4fe1\u606f\u5728\u7cfb\u7edf\u4e2d\u5c31\u662f\u4e00\u4e2a(x,y)\u5750\u6807\uff0c\u8f66\u8f86\u4fe1\u606f\u5305\u62ec\u8f66\u7684\u53f7\u724c\uff0c\u989c\u8272\uff0c\u54c1\u724c\u548c\u6240\u5c5e\u516c\u53f8\uff0c\u5728\u8c03\u5ea6\u7cfb\u7edf\u5b58\u50a8\u7684\u51fa\u79df\u8f66\u884c\u9a76\u8f68\u8ff9\u4e2d\uff0c\u4f4d\u7f6e\u662f\u5b9e\u65f6\u5728\u53d8\u5316\u7684\uff0c\u4f46\u8f66\u8f86\u4fe1\u606f\u5c31\u53ef\u4ee5\u901a\u8fc7\u4eab\u5143\u6a21\u5f0f\u5171\u7528\u4e00\u4e2a\u5bf9\u8c61\u5f15\u7528\uff0c\u6765\u51cf\u5c11\u5185\u5b58\u6d88\u8017\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u51fa\u79df\u8f66\u4eab\u5143\u5bf9\u8c61<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package flyweight\n\nimport (\n  &quot;fmt&quot;\n)\n\n\/\/ Taxi \u51fa\u79df\u8f66\uff0c\u4eab\u5143\u5bf9\u8c61\uff0c\u4fdd\u5b58\u4e0d\u53d8\u7684\u5185\u5728\u5c5e\u6027\u4fe1\u606f\ntype Taxi struct {\n  licensePlate string \/\/ \u8f66\u724c\n  color        string \/\/ \u989c\u8272\n  brand        string \/\/ \u6c7d\u8f66\u54c1\u724c\n  company      string \/\/ \u6240\u5c5e\u516c\u53f8\n}\n\n\/\/ LocateFor \u83b7\u53d6\u5b9a\u4f4d\u4fe1\u606f\nfunc (t *Taxi) LocateFor(monitorMap string, x, y int) string {\n  return fmt.Sprintf(&quot;%s,\u5bf9\u4e8e\u8f66\u724c\u53f7%s,%s,%s\u54c1\u724c,\u6240\u5c5e%s\u516c\u53f8,\u5b9a\u4f4d(%d,%d)&quot;, monitorMap,\n    t.licensePlate, t.color, t.brand, t.company, x, y)\n}\n\n\/\/ taxiFactoryInstance \u51fa\u79df\u8f66\u5de5\u5382\u5355\u4f8b\nvar taxiFactoryInstance = &amp;TaxiFactory{\n  taxis: make(map[string]*Taxi),\n}\n\n\/\/ GetTaxiFactory \u83b7\u53d6\u51fa\u79df\u8f66\u5de5\u5382\u5355\u4f8b\nfunc GetTaxiFactory() *TaxiFactory {\n  return taxiFactoryInstance\n}\n\n\/\/ TaxiFactory \u51fa\u79df\u8f66\u5de5\u5382\u7c7b\ntype TaxiFactory struct {\n  taxis map[string]*Taxi \/\/ key\u4e3a\u8f66\u724c\u53f7\n}\n\n\/\/ getTaxi \u83b7\u53d6\u51fa\u79df\u8f66\nfunc (f *TaxiFactory) getTaxi(licensePlate, color, brand, company string) *Taxi {\n  if _, ok := f.taxis[licensePlate]; !ok {\n    f.taxis[licensePlate] = &amp;Taxi{\n      licensePlate: licensePlate,\n      color:        color,\n      brand:        brand,\n      company:      company,\n    }\n  }\n  return f.taxis[licensePlate]\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package flyweight\n\nimport &quot;bytes&quot;\n\n\/\/ TaxiPosition \u51fa\u79df\u8f66\u4f4d\u7f6e\u4fe1\u606f x,y\u4e3a\u5916\u5728\u6570\u636e\u4fe1\u606f\uff0ctaxi\u4e3a\u5185\u5728\u6570\u636e\u4fe1\u606f\uff08\u4eab\u5143\u5bf9\u8c61\uff09\ntype TaxiPosition struct {\n  x    int\n  y    int\n  taxi *Taxi\n}\n\nfunc NewTaxiPosition(taxi *Taxi, x, y int) *TaxiPosition {\n  return &amp;TaxiPosition{\n    taxi: taxi,\n    x:    x,\n    y:    y,\n  }\n}\n\n\/\/ LocateFor \u5b9a\u4f4d\u4fe1\u606f\nfunc (p *TaxiPosition) LocateFor(monitorMap string) string {\n  return p.taxi.LocateFor(monitorMap, p.x, p.y)\n}\n\n\/\/ TaxiDispatcher \u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf\ntype TaxiDispatcher struct {\n  name   string\n  traces map[string][]*TaxiPosition \/\/ \u5b58\u50a8\u51fa\u79df\u8f66\u5f53\u5929\u8f68\u8ff9\u4fe1\u606f\uff0ckey\u4e3a\u8f66\u724c\u53f7\n}\n\nfunc NewTaxiDispatcher(name string) *TaxiDispatcher {\n  return &amp;TaxiDispatcher{\n    name:   name,\n    traces: make(map[string][]*TaxiPosition),\n  }\n}\n\n\/\/ AddTrace \u6dfb\u52a0\u8f68\u8ff9\nfunc (t *TaxiDispatcher) AddTrace(licensePlate, color, brand, company string, x, y int) {\n  taxi := GetTaxiFactory().getTaxi(licensePlate, color, brand, company)\n  t.traces[licensePlate] = append(t.traces[licensePlate], NewTaxiPosition(taxi, x, y))\n}\n\n\/\/ ShowTraces \u663e\u793a\u8f68\u8ff9\nfunc (t *TaxiDispatcher) ShowTraces(licensePlate string) string {\n  bytesBuf := bytes.Buffer{}\n  for _, trace := range t.traces[licensePlate] {\n    bytesBuf.WriteString(trace.LocateFor(t.name))\n    bytesBuf.WriteByte('\/n')\n  }\n  return bytesBuf.String()\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package flyweight\n\nimport (\n   &quot;fmt&quot;\n   &quot;testing&quot;\n)\n\nfunc TestFlyweight(t *testing.T) {\n   dispatcher := NewTaxiDispatcher(&quot;\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf&quot;)\n   dispatcher.AddTrace(&quot;\u4eacB.123456&quot;, &quot;\u9ec4\u8272&quot;, &quot;\u5317\u4eac\u73b0\u4ee3&quot;, &quot;\u5317\u6c7d&quot;, 10, 20)\n   dispatcher.AddTrace(&quot;\u4eacB.123456&quot;, &quot;\u9ec4\u8272&quot;, &quot;\u5317\u4eac\u73b0\u4ee3&quot;, &quot;\u5317\u6c7d&quot;, 20, 30)\n   dispatcher.AddTrace(&quot;\u4eacB.123456&quot;, &quot;\u9ec4\u8272&quot;, &quot;\u5317\u4eac\u73b0\u4ee3&quot;, &quot;\u5317\u6c7d&quot;, 30, 40)\n   dispatcher.AddTrace(&quot;\u4eacB.123456&quot;, &quot;\u9ec4\u8272&quot;, &quot;\u5317\u4eac\u73b0\u4ee3&quot;, &quot;\u5317\u6c7d&quot;, 40, 50)\n\n   dispatcher.AddTrace(&quot;\u4eacB.567890&quot;, &quot;\u7ea2\u8272&quot;, &quot;\u4e00\u6c7d\u5927\u4f17&quot;, &quot;\u9996\u6c7d&quot;, 20, 40)\n   dispatcher.AddTrace(&quot;\u4eacB.567890&quot;, &quot;\u7ea2\u8272&quot;, &quot;\u4e00\u6c7d\u5927\u4f17&quot;, &quot;\u9996\u6c7d&quot;, 50, 50)\n\n   fmt.Println(dispatcher.ShowTraces(&quot;\u4eacB.123456&quot;))\n   fmt.Println(dispatcher.ShowTraces(&quot;\u4eacB.567890&quot;))\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestFlyweight\n\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf,\u5bf9\u4e8e\u8f66\u724c\u53f7\u4eacB.123456,\u9ec4\u8272,\u5317\u4eac\u73b0\u4ee3\u54c1\u724c,\u6240\u5c5e\u5317\u6c7d\u516c\u53f8,\u5b9a\u4f4d(10,20)\n\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf,\u5bf9\u4e8e\u8f66\u724c\u53f7\u4eacB.123456,\u9ec4\u8272,\u5317\u4eac\u73b0\u4ee3\u54c1\u724c,\u6240\u5c5e\u5317\u6c7d\u516c\u53f8,\u5b9a\u4f4d(20,30)\n\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf,\u5bf9\u4e8e\u8f66\u724c\u53f7\u4eacB.123456,\u9ec4\u8272,\u5317\u4eac\u73b0\u4ee3\u54c1\u724c,\u6240\u5c5e\u5317\u6c7d\u516c\u53f8,\u5b9a\u4f4d(30,40)\n\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf,\u5bf9\u4e8e\u8f66\u724c\u53f7\u4eacB.123456,\u9ec4\u8272,\u5317\u4eac\u73b0\u4ee3\u54c1\u724c,\u6240\u5c5e\u5317\u6c7d\u516c\u53f8,\u5b9a\u4f4d(40,50)\n\n\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf,\u5bf9\u4e8e\u8f66\u724c\u53f7\u4eacB.567890,\u7ea2\u8272,\u4e00\u6c7d\u5927\u4f17\u54c1\u724c,\u6240\u5c5e\u9996\u6c7d\u516c\u53f8,\u5b9a\u4f4d(20,40)\n\u5317\u4eac\u5e02\u51fa\u79df\u8f66\u8c03\u5ea6\u7cfb\u7edf,\u5bf9\u4e8e\u8f66\u724c\u53f7\u4eacB.567890,\u7ea2\u8272,\u4e00\u6c7d\u5927\u4f17\u54c1\u724c,\u6240\u5c5e\u9996\u6c7d\u516c\u53f8,\u5b9a\u4f4d(50,50)\n--- PASS: TestFlyweight (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916594\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u4ee3\u7406\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u4ee3\u7406\u662f\u4e00\u79cd\u7ed3\u6784\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u8ba9\u4f60\u80fd\u63d0\u4f9b\u771f\u5b9e\u670d\u52a1\u5bf9\u8c61\u7684\u66ff\u4ee3\u54c1\u7ed9\u5ba2\u6237\u7aef\u4f7f\u7528\u3002\u4ee3\u7406\u63a5\u6536\u5ba2\u6237\u7aef\u7684\u8bf7\u6c42\u5e76\u8fdb\u884c\u4e00\u4e9b\u5904\u7406 \uff08\u8bbf\u95ee\u63a7\u5236\u548c\u7f13\u5b58\u7b49\uff09\uff0c \u7136\u540e\u518d\u5c06\u8bf7\u6c42\u4f20\u9012\u7ed9\u670d\u52a1\u5bf9\u8c61\u3002<\/p>\n<p>\u4ee3\u7406\u5bf9\u8c61\u62e5\u6709\u548c\u670d\u52a1\u5bf9\u8c61\u76f8\u540c\u7684\u63a5\u53e3\uff0c\u8fd9\u4f7f\u5f97\u5f53\u5176\u88ab\u4f20\u9012\u7ed9\u5ba2\u6237\u7aef\u65f6\u53ef\u4e0e\u771f\u5b9e\u5bf9\u8c61\u4e92\u6362\u3002<\/p>\n<p>\u4fee\u9970\u4e0e\u4ee3\u7406\u662f\u975e\u5e38\u76f8\u4f3c\u7684\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u90fd\u662f\u57fa\u4e8e\u7ec4\u5408\u8bbe\u8ba1\u539f\u5219\uff0c\u4e5f\u5c31\u662f\u8bf4\u4e00\u4e2a\u5bf9\u8c61\u5e94\u8be5\u5c06\u90e8\u5206\u5de5\u4f5c\u59d4\u6d3e\u7ed9\u53e6\u4e00\u4e2a\u5bf9\u8c61\u3002\u4f46\u4e24\u8005\u4e4b\u95f4\u4e0d\u540c\u70b9\u6211\u8ba4\u4e3a\u662f\uff0c\u4fee\u9970\u5668\u6a21\u5f0f\u603b\u662f\u8981\u6267\u884c\u670d\u52a1\u5bf9\u8c61\uff0c\u5bf9\u4e8e\u6267\u884c\u4e4b\u524d\u6216\u6267\u884c\u4e4b\u540e\u7ed3\u679c\u8fdb\u884c\u52a0\u5f3a\uff0c\u670d\u52a1\u5bf9\u8c61\u57fa\u672c\u662f\u5ba2\u6237\u7aef\u521b\u5efa\u597d\u518d\u5d4c\u5957\u5916\u5c42\u7684\u4fee\u9970\u5bf9\u8c61\uff1b\u800c\u4ee3\u7406\u6a21\u5f0f\u4e0d\u4e00\u5b9a\u6267\u884c\u670d\u52a1\u5bf9\u8c61\uff0c\u6709\u53ef\u80fd\u901a\u8fc7\u7f13\u5b58\uff0c\u5ef6\u8fdf\u52a0\u8f7d\u7b49\u6ca1\u6709\u8bbf\u95ee\u670d\u52a1\u5bf9\u8c61\uff0c\u540c\u65f6\u670d\u52a1\u5bf9\u8c61\u4ec0\u4e48\u65f6\u5019\u521b\u5efa\u4e5f\u662f\u7531\u4ee3\u7406\u7c7b\u51b3\u5b9a\u7684\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u623f\u5c4b\u4e2d\u4ecb\u4ee3\u7406\u5e2e\u52a9\u623f\u4e1c\u5356\u623f\u5b50\uff0c\u8fd9\u4e2a\u8fc7\u7a0b\u5c31\u662f\u4e00\u4e2a\u4ee3\u7406\u6a21\u5f0f\u7684\u8fc7\u7a0b\uff0c\u4e2d\u4ecb\u4f1a\u6536\u96c6\u5c3d\u91cf\u591a\u7684\u5356\u623f\u4fe1\u606f\uff0c\u5e76\u901a\u8fc7\u5404\u79cd\u6e20\u9053\u53d1\u5e03\uff0c\u540c\u65f6\u4e2d\u4ecb\u4f1a\u968f\u65f6\u5e26\u5ba2\u6237\u770b\u623f\uff0c\u5e76\u521d\u6b65\u5546\u8ba8\u4ef7\u683c\uff0c\u5982\u679c\u8fbe\u6210\u521d\u6b65\u8d2d\u4e70\u610f\u5411\uff0c\u624d\u4f1a\u7ea6\u623f\u4e1c\u8ba8\u8bba\u623f\u5c4b\u4ef7\u683c\uff0c\u6700\u540e\u7b7e\u7ea6\u5356\u623f\uff1b\u623f\u5c4b\u4e2d\u4ecb\u4e0e\u623f\u4e1c\u90fd\u5b9e\u73b0\u5356\u623f\u63a5\u53e3\uff0c\u4e2d\u4ecb\u4f1a\u63d0\u524d\u5750\u4e00\u4e9b\u524d\u671f\u5de5\u4f5c\uff0c\u5982\u679c\u90fd\u6ca1\u95ee\u9898\uff0c\u624d\u4f1a\u7ea6\u623f\u4e1c\u6267\u884c\u771f\u6b63\u7684\u7b7e\u7ea6\u5356\u623f\u6d41\u7a0b\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u623f\u5c4b\u4e2d\u4ecb\u5356\u623f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package proxy\n\nimport (\n  &quot;bytes&quot;\n  &quot;fmt&quot;\n)\n\n\/\/ HouseSeller \u623f\u5c4b\u51fa\u552e\u8005\ntype HouseSeller interface {\n  SellHouse(address string, buyer string) string\n}\n\n\/\/ houseProxy \u623f\u4ea7\u4e2d\u4ecb\u4ee3\u7406\ntype houseProxy struct {\n  houseSeller HouseSeller\n}\n\nfunc NewHouseProxy(houseSeller HouseSeller) *houseProxy {\n  return &amp;houseProxy{\n    houseSeller: houseSeller,\n  }\n}\n\n\/\/ SellHouse \u4e2d\u4ecb\u5356\u623f\uff0c\u770b\u623f-&gt;\u521d\u6b65\u8c08\u4ef7-&gt;\u6700\u7ec8\u548c\u623f\u4e1c\u7b7e\u534f\u8bae\nfunc (h *houseProxy) SellHouse(address string, buyer string) string {\n  buf := bytes.Buffer{}\n  buf.WriteString(h.viewHouse(address, buyer) + &quot;\/n&quot;)\n  buf.WriteString(h.preBargain(address, buyer) + &quot;\/n&quot;)\n  buf.WriteString(h.houseSeller.SellHouse(address, buyer))\n  return buf.String()\n}\n\n\/\/ viewHouse \u770b\u623f\u4ecb\u7ecd\u57fa\u672c\u60c5\u51b5\nfunc (h *houseProxy) viewHouse(address string, buyer string) string {\n  return fmt.Sprintf(&quot;\u5e26\u4e70\u5bb6%s\u770b\u4f4d\u4e8e%s\u7684\u623f\u5c4b\uff0c\u5e76\u4ecb\u7ecd\u57fa\u672c\u60c5\u51b5&quot;, buyer, address)\n}\n\n\/\/ preBargain \u521d\u6b65\u6c9f\u901a\u4ef7\u683c\nfunc (h *houseProxy) preBargain(address string, buyer string) string {\n  return fmt.Sprintf(&quot;\u8ba8\u4ef7\u8fd8\u4ef7\u540e\uff0c\u521d\u6b65\u8fbe\u6210\u8d2d\u4e70\u610f\u5411&quot;)\n}\n\n\/\/ houseOwner \u623f\u4e1c\ntype houseOwner struct{}\n\n\/\/ SellHouse \u623f\u4e1c\u5356\u623f\uff0c\u5546\u8ba8\u4ef7\u683c\uff0c\u7b7e\u7f72\u8d2d\u623f\u534f\u8bae\nfunc (h *houseOwner) SellHouse(address string, buyer string) string {\n  return fmt.Sprintf(&quot;\u6700\u7ec8\u5546\u8ba8\u4ef7\u683c\u540e\uff0c\u4e0e%s\u7b7e\u7f72\u8d2d\u4e70\u5730\u5740\u4e3a%s\u7684\u8d2d\u623f\u534f\u8bae\u3002&quot;, buyer, address)\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u6d4b\u8bd5\u7a0b\u5e8f<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package proxy\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestProxy(t *testing.T) {\n  proxy := NewHouseProxy(&amp;houseOwner{})\n  fmt.Println(proxy.SellHouse(&quot;\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u4e2d\u5173\u6751\u5927\u8857\uff0c2\u53f7\u96621\u53f7\u697c4\u5355\u5143502\u5ba4&quot;, &quot;\u674e\u56db&quot;))\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u884c\u7ed3\u679c<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>=== RUN   TestProxy\n\u5e26\u4e70\u5bb6\u674e\u56db\u770b\u4f4d\u4e8e\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u4e2d\u5173\u6751\u5927\u8857\uff0c2\u53f7\u96621\u53f7\u697c4\u5355\u5143502\u5ba4\u7684\u623f\u5c4b\uff0c\u5e76\u4ecb\u7ecd\u57fa\u672c\u60c5\u51b5\n\u8ba8\u4ef7\u8fd8\u4ef7\u540e\uff0c\u521d\u6b65\u8fbe\u6210\u8d2d\u4e70\u610f\u5411\n\u6700\u7ec8\u5546\u8ba8\u4ef7\u683c\u540e\uff0c\u4e0e\u674e\u56db\u7b7e\u7f72\u8d2d\u4e70\u5730\u5740\u4e3a\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u4e2d\u5173\u6751\u5927\u8857\uff0c2\u53f7\u96621\u53f7\u697c4\u5355\u5143502\u5ba4\u7684\u8d2d\u623f\u534f\u8bae\u3002\n--- PASS: TestProxy (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916595\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u5de5\u5382\u65b9\u6cd5\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u5de5\u5382\u65b9\u6cd5\u6a21\u5f0f\u662f\u4e00\u79cd\u521b\u5efa\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5176\u5728\u7236\u7c7b\u4e2d\u63d0\u4f9b\u4e00\u4e2a\u521b\u5efa\u5bf9\u8c61\u7684\u65b9\u6cd5\uff0c \u5141\u8bb8\u5b50\u7c7b\u51b3\u5b9a\u5b9e\u4f8b\u5316\u5bf9\u8c61\u7684\u7c7b\u578b\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u644a\u714e\u997c\u7684\u5c0f\u8d29\u9700\u8981\u5148\u644a\u4e2a\u714e\u997c\uff0c\u518d\u5356\u51fa\u53bb\uff0c\u644a\u714e\u997c\u5c31\u53ef\u4ee5\u7c7b\u6bd4\u4e3a\u4e00\u4e2a\u5de5\u5382\u65b9\u6cd5\uff0c\u6839\u636e\u987e\u5ba2\u7684\u559c\u597d\u644a\u51fa\u4e0d\u540c\u53e3\u5473\u7684\u714e\u997c\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u63a5\u53e3<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package factorymethod\n\n\/\/ Pancake \u714e\u997c\ntype Pancake interface {\n  \/\/ ShowFlour \u714e\u997c\u4f7f\u7528\u7684\u9762\u7c89\n  ShowFlour() string\n  \/\/ Value \u714e\u997c\u4ef7\u683c\n  Value() float32\n}\n\n\/\/ PancakeCook \u714e\u997c\u53a8\u5e08\ntype PancakeCook interface {\n  \/\/ MakePancake \u644a\u714e\u997c\n  MakePancake() Pancake\n}\n\n\/\/ PancakeVendor \u714e\u997c\u5c0f\u8d29\ntype PancakeVendor struct {\n  PancakeCook\n}\n\n\/\/ NewPancakeVendor ...\nfunc NewPancakeVendor(cook PancakeCook) *PancakeVendor {\n  return &amp;PancakeVendor{\n    PancakeCook: cook,\n  }\n}\n\n\/\/ SellPancake \u5356\u714e\u997c\uff0c\u5148\u644a\u714e\u997c\uff0c\u518d\u5356\nfunc (vendor *PancakeVendor) SellPancake() (money float32) {\n  return vendor.MakePancake().Value()\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<p>\u5404\u79cd\u9762\u7684\u714e\u997c\u5b9e\u73b0<\/p>\n<pre><code>package factorymethod\n\n\/\/ cornPancake \u7389\u7c73\u9762\u714e\u997c\ntype cornPancake struct{}\n\n\/\/ NewCornPancake ...\nfunc NewCornPancake() *cornPancake {\n  return &amp;cornPancake{}\n}\n\nfunc (cake *cornPancake) ShowFlour() string {\n  return &quot;\u7389\u7c73\u9762&quot;\n}\n\nfunc (cake *cornPancake) Value() float32 {\n  return 5.0\n}\n\n\/\/ milletPancake \u5c0f\u7c73\u9762\u714e\u997c\ntype milletPancake struct{}\n\nfunc NewMilletPancake() *milletPancake {\n  return &amp;milletPancake{}\n}\n\nfunc (cake *milletPancake) ShowFlour() string {\n  return &quot;\u5c0f\u7c73\u9762&quot;\n}\n\nfunc (cake *milletPancake) Value() float32 {\n  return 8.0\n}<\/code><\/pre>\n<p>\u5236\u4f5c\u5404\u79cd\u53e3\u5473\u714e\u997c\u7684\u5de5\u5382\u65b9\u6cd5\u5b9e\u73b0<\/p>\n<pre><code>package factorymethod\n\n\/\/ cornPancakeCook \u5236\u4f5c\u7389\u7c73\u9762\u714e\u997c\u53a8\u5e08\ntype cornPancakeCook struct{}\n\nfunc NewCornPancakeCook() *cornPancakeCook {\n  return &amp;cornPancakeCook{}\n}\n\nfunc (cook *cornPancakeCook) MakePancake() Pancake {\n  return NewCornPancake()\n}\n\n\/\/ milletPancakeCook \u5236\u4f5c\u5c0f\u7c73\u9762\u714e\u997c\u53a8\u5e08\ntype milletPancakeCook struct{}\n\nfunc NewMilletPancakeCook() *milletPancakeCook {\n  return &amp;milletPancakeCook{}\n}\n\nfunc (cook *milletPancakeCook) MakePancake() Pancake {\n  return NewMilletPancake()\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u7528<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package factorymethod\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestFactoryMethod(t *testing.T) {\n  pancakeVendor := NewPancakeVendor(NewCornPancakeCook())\n  fmt.Printf(&quot;Corn pancake value is %v\/n&quot;, pancakeVendor.SellPancake())\n\n  pancakeVendor = NewPancakeVendor(NewMilletPancakeCook())\n  fmt.Printf(&quot;Millet pancake value is %v\/n&quot;, pancakeVendor.SellPancake())\n}<\/code><\/pre>\n<p>\u8f93\u51fa\uff1a<\/p>\n<pre><code>=== RUN   TestFactoryMethod\nCorn pancake value is 5\nMillet pancake value is 8\n--- PASS: TestFactoryMethod (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916596\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u62bd\u8c61\u5de5\u5382\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u62bd\u8c61\u5de5\u5382\u662f\u4e00\u79cd\u521b\u5efa\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u5b83\u80fd\u521b\u5efa\u4e00\u7cfb\u5217\u76f8\u5173\u7684\u5bf9\u8c61\uff0c\u800c\u65e0\u9700\u6307\u5b9a\u5176\u5177\u4f53\u7c7b\u3002<\/p>\n<p>\u62bd\u8c61\u5de5\u5382\u5b9a\u4e49\u4e86\u7528\u4e8e\u521b\u5efa\u4e0d\u540c\u4ea7\u54c1\u7684\u63a5\u53e3\uff0c\u4f46\u5c06\u5b9e\u9645\u7684\u521b\u5efa\u5de5\u4f5c\u7559\u7ed9\u4e86\u5177\u4f53\u5de5\u5382\u7c7b\u3002\u6bcf\u4e2a\u5de5\u5382\u7c7b\u578b\u90fd\u5bf9\u5e94\u4e00\u4e2a\u7279\u5b9a\u7684\u4ea7\u54c1\u53d8\u4f53\u3002<\/p>\n<p>\u5728\u521b\u5efa\u4ea7\u54c1\u65f6\uff0c\u5ba2\u6237\u7aef\u4ee3\u7801\u8c03\u7528\u7684\u662f\u5de5\u5382\u5bf9\u8c61\u7684\u6784\u5efa\u65b9\u6cd5\uff0c\u800c\u4e0d\u662f\u76f4\u63a5\u8c03\u7528\u6784\u9020\u51fd\u6570 \uff08 new\u64cd\u4f5c\u7b26\uff09\u3002\u7531\u4e8e\u4e00\u4e2a\u5de5\u5382\u5bf9\u5e94\u4e00\u79cd\u4ea7\u54c1\u53d8\u4f53\uff0c\u56e0\u6b64\u5b83\u521b\u5efa\u7684\u6240\u6709\u4ea7\u54c1\u90fd\u53ef\u76f8\u4e92\u517c\u5bb9\u3002<\/p>\n<p>\u5ba2\u6237\u7aef\u4ee3\u7801\u4ec5\u901a\u8fc7\u5176\u62bd\u8c61\u63a5\u53e3\u4e0e\u5de5\u5382\u548c\u4ea7\u54c1\u8fdb\u884c\u4ea4\u4e92\u3002\u8be5\u63a5\u53e3\u5141\u8bb8\u540c\u4e00\u5ba2\u6237\u7aef\u4ee3\u7801\u4e0e\u4e0d\u540c\u4ea7\u54c1\u8fdb\u884c\u4ea4\u4e92\u3002\u4f60\u53ea\u9700\u521b\u5efa\u4e00\u4e2a\u5177\u4f53\u5de5\u5382\u7c7b\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u5ba2\u6237\u7aef\u4ee3\u7801\u5373\u53ef\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u53a8\u5e08\u51c6\u5907\u4e00\u9910\u65f6\uff0c\u4f1a\u5206\u522b\u505a\u5403\u7684\u548c\u559d\u7684\uff0c\u6839\u636e\u65e9\u3001\u4e2d\u3001\u665a\u4e09\u9910\u996e\u98df\u4e60\u60ef\uff0c\u4f1a\u5206\u522b\u5236\u4f5c\u4e0d\u540c\u7684\u996e\u98df\uff0c\u53a8\u5e08\u5c31\u76f8\u5f53\u4e8e\u62bd\u8c61\u5de5\u5382\uff0c\u5236\u4f5c\u4e09\u9910\u7684\u4e0d\u540c\u70f9\u996a\u65b9\u5f0f\u5c31\u597d\u6bd4\u4e0d\u540c\u62bd\u8c61\u5de5\u5382\u7684\u5b9e\u73b0\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u63a5\u53e3<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package abstractfactory\n\/\/ Cook \u53a8\u5e08\u63a5\u53e3\uff0c\u62bd\u8c61\u5de5\u5382\ntype Cook interface {\n  \/\/ MakeFood \u5236\u4f5c\u4e3b\u98df\n  MakeFood() Food\n  \/\/ MakeDrink \u5236\u4f5c\u996e\u54c1\n  MakeDrink() Drink\n}\n\n\/\/ Food \u4e3b\u98df\u63a5\u53e3\ntype Food interface {\n  \/\/ Eaten \u88ab\u5403\n  Eaten() string\n}\n\n\/\/ Drink \u996e\u54c1\u63a5\u53e3\ntype Drink interface {\n  \/\/ Drunk \u88ab\u559d\n  Drunk() string\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<p>\u4e09\u9910\u4e0d\u540c\u53a8\u5e08\u63a5\u53e3\u7684\u5b9e\u73b0<\/p>\n<pre><code>package abstractfactory\n\n\/\/ breakfastCook \u65e9\u9910\u53a8\u5e08\ntype breakfastCook struct{}\n\nfunc NewBreakfastCook() *breakfastCook {\n  return &amp;breakfastCook{}\n}\n\nfunc (b *breakfastCook) MakeFood() Food {\n  return &amp;cakeFood{&quot;\u5207\u7247\u9762\u5305&quot;}\n}\n\nfunc (b *breakfastCook) MakeDrink() Drink {\n  return &amp;gruelDrink{&quot;\u5c0f\u7c73\u7ca5&quot;}\n}\n\n\/\/ lunchCook \u5348\u9910\u53a8\u5e08\ntype lunchCook struct{}\n\nfunc NewLunchCook() *lunchCook {\n  return &amp;lunchCook{}\n}\n\nfunc (l *lunchCook) MakeFood() Food {\n  return &amp;dishFood{&quot;\u70e4\u5168\u7f8a&quot;}\n}\n\nfunc (l *lunchCook) MakeDrink() Drink {\n  return &amp;sodaDrink{&quot;\u51b0\u9547\u53ef\u53e3\u53ef\u4e50&quot;}\n}\n\n\/\/ dinnerCook \u665a\u9910\u53a8\u5e08\ntype dinnerCook struct{}\n\nfunc NewDinnerCook() *dinnerCook {\n  return &amp;dinnerCook{}\n}\n\nfunc (d *dinnerCook) MakeFood() Food {\n  return &amp;noodleFood{&quot;\u5927\u76d8\u9e21\u62cc\u9762&quot;}\n}\n\nfunc (d *dinnerCook) MakeDrink() Drink {\n  return &amp;soupDrink{&quot;\u897f\u7ea2\u67ff\u9e21\u86cb\u6c64&quot;}\n}<\/code><\/pre>\n<p>\u4e0d\u540c\u5403\u7684<\/p>\n<pre><code>package abstractfactory\n\nimport &quot;fmt&quot;\n\n\/\/ cakeFood \u86cb\u7cd5\ntype cakeFood struct {\n  cakeName string\n}\n\nfunc (c *cakeFood) Eaten() string {\n  return fmt.Sprintf(&quot;%v\u88ab\u5403&quot;, c.cakeName)\n}\n\n\/\/ dishFood \u83dc\u80b4\ntype dishFood struct {\n  dishName string\n}\n\nfunc (d *dishFood) Eaten() string {\n  return fmt.Sprintf(&quot;%v\u88ab\u5403&quot;, d.dishName)\n}\n\n\/\/ noodleFood \u9762\u6761\ntype noodleFood struct {\n  noodleName string\n}\n\nfunc (n *noodleFood) Eaten() string {\n  return fmt.Sprintf(&quot;%v\u88ab\u5403&quot;, n.noodleName)\n}<\/code><\/pre>\n<p>\u4e0d\u540c\u559d\u7684<\/p>\n<pre><code>package abstractfactory\n\nimport &quot;fmt&quot;\n\n\/\/ gruelDrink \u7ca5\ntype gruelDrink struct {\n  gruelName string\n}\n\nfunc (g *gruelDrink) Drunk() string {\n  return fmt.Sprintf(&quot;%v\u88ab\u559d&quot;, g.gruelName)\n}\n\n\/\/ sodaDrink \u6c7d\u6c34\ntype sodaDrink struct {\n  sodaName string\n}\n\nfunc (s *sodaDrink) Drunk() string {\n  return fmt.Sprintf(&quot;%v\u88ab\u559d&quot;, s.sodaName)\n}\n\n\/\/ soupDrink \u6c64\ntype soupDrink struct {\n  soupName string\n}\n\nfunc (s *soupDrink) Drunk() string {\n  return fmt.Sprintf(&quot;%v\u88ab\u559d&quot;, s.soupName)\n}<\/code><\/pre>\n<h4><strong>\u8fd0\u7528<\/strong><\/h4>\n<pre><code>package abstractfactory\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestAbstractFactory(t *testing.T) {\n  fmt.Printf(&quot;breakfast: %v\/n&quot;, HaveMeal(NewBreakfastCook()))\n  fmt.Printf(&quot;lunch: %v\/n&quot;, HaveMeal(NewLunchCook()))\n  fmt.Printf(&quot;dinner: %v\/n&quot;, HaveMeal(NewDinnerCook()))\n}\n\n\/\/ HaveMeal \u5403\u996d\nfunc HaveMeal(cook Cook) string {\n  return fmt.Sprintf(&quot;%s %s&quot;, cook.MakeFood().Eaten(), cook.MakeDrink().Drunk())\n}<\/code><\/pre>\n<p>\u8f93\u51fa<\/p>\n<pre><code>=== RUN   TestAbstractFactory\nbreakfast: \u5207\u7247\u9762\u5305\u88ab\u5403 \u5c0f\u7c73\u7ca5\u88ab\u559d\nlunch: \u70e4\u5168\u7f8a\u88ab\u5403 \u51b0\u9547\u53ef\u53e3\u53ef\u4e50\u88ab\u559d\ndinner: \u5927\u76d8\u9e21\u62cc\u9762\u88ab\u5403 \u897f\u7ea2\u67ff\u9e21\u86cb\u6c64\u88ab\u559d\n--- PASS: TestAbstractFactory (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916597\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u751f\u6210\u5668\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u751f\u6210\u5668\u662f\u4e00\u79cd\u521b\u5efa\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u4f7f\u4f60\u80fd\u591f\u5206\u6b65\u9aa4\u521b\u5efa\u590d\u6742\u5bf9\u8c61\u3002<\/p>\n<p>\u4e0e\u5176\u4ed6\u521b\u5efa\u578b\u6a21\u5f0f\u4e0d\u540c\uff0c\u751f\u6210\u5668\u4e0d\u8981\u6c42\u4ea7\u54c1\u62e5\u6709\u901a\u7528\u63a5\u53e3\u3002\u8fd9\u4f7f\u5f97\u7528\u76f8\u540c\u7684\u521b\u5efa\u8fc7\u7a0b\u751f\u6210\u4e0d\u540c\u7684\u4ea7\u54c1\u6210\u4e3a\u53ef\u80fd\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u8fd8\u662f\u644a\u714e\u997c\u7684\u4f8b\u5b50\uff0c\u644a\u714e\u997c\u5206\u4e3a\u56db\u4e2a\u6b65\u9aa4\uff0c1\u653e\u9762\u7cca\u30012\u653e\u9e21\u86cb\u30013\u653e\u8c03\u6599\u30014\u653e\u8584\u8106\uff0c\u901a\u8fc7\u56db\u4e2a\u521b\u5efa\u8fc7\u7a0b\uff0c\u5236\u4f5c\u597d\u4e00\u4e2a\u714e\u997c\uff0c\u8fd9\u4e2a\u644a\u714e\u997c\u7684\u8fc7\u7a0b\u5c31\u597d\u6bd4\u714e\u997c\u751f\u6210\u5668\u63a5\u53e3\uff0c\u4e0d\u540c\u751f\u6210\u5668\u7684\u5b9e\u73b0\u5c31\u76f8\u5f53\u4e8e\u644a\u4e0d\u540c\u54c1\u7c7b\u7684\u714e\u997c\uff0c\u6bd4\u5982\u6b63\u5e38\u7684\u714e\u997c\uff0c\u5065\u5eb7\u7684\u714e\u997c\uff08\u53ef\u80fd\u7528\u7684\u662f\u7c97\u7cae\u9762\u3001\u67f4\u9e21\u86cb\u3001\u975e\u6cb9\u70b8\u8584\u8106\u3001\u4e0d\u653e\u9171\u7b49\uff09\uff0c\u751f\u6210\u5668\u63a5\u53e3\u65b9\u6cd5\u4e5f\u53ef\u4ee5\u901a\u8fc7\u53c2\u6570\u63a7\u5236\u714e\u997c\u7684\u5927\u5c0f\uff0c\u6bd4\u5982\u653e\u4e24\u52fa\u9762\u7cca\uff0c\u653e2\u4e2a\u9e21\u86cb\u7b49\u3002<\/p>\n<p>\u751f\u6210\u5668\u7684\u4f7f\u7528\u8005\u4e3a\u4e86\u907f\u514d\u6bcf\u6b21\u90fd\u8c03\u7528\u76f8\u540c\u7684\u6784\u5efa\u6b65\u9aa4\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u5305\u88c5\u7c7b\u56fa\u5b9a\u51e0\u79cd\u6784\u5efa\u8fc7\u7a0b\uff0c\u751f\u6210\u51e0\u7c7b\u5e38\u7528\u7684\u4ea7\u54c1\uff0c\u5c31\u597d\u50cf\u644a\u714e\u997c\u6709\u51e0\u7c7b\u5e38\u5356\u56fa\u5b9a\u6210\u54c1\uff0c\u6bd4\u5982\u666e\u901a\u7684\uff0c\u52a0\u4e24\u4e2a\u9e21\u86cb\u7684\uff0c\u4e0d\u8981\u9999\u83dc\u7684\u7b49\u7b49\uff0c\u8fd9\u51e0\u7c7b\u56fa\u5b9a\u6784\u5efa\u8fc7\u7a0b\u63d0\u524d\u5b9a\u5236\u597d\uff0c\u76f4\u63a5\u901a\u8fc7\u7b80\u5355\u5de5\u5382\u65b9\u6cd5\u5c31\u76f4\u63a5\u521b\u5efa\uff0c\u5982\u679c\u7528\u6237\u518d\u9700\u8981\u7ec6\u7c92\u5ea6\u7684\u5b9a\u5236\u6784\u5efa\uff0c\u518d\u901a\u8fc7\u751f\u6210\u5668\u521b\u5efa\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u63a5\u53e3<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package builder\n\n\/\/ Quantity \u5206\u91cf\ntype Quantity int\n\nconst (\n  Small  Quantity = 1\n  Middle Quantity = 5\n  Large  Quantity = 10\n)\n\ntype PancakeBuilder interface {\n  \/\/ PutPaste \u653e\u9762\u7cca\n  PutPaste(quantity Quantity)\n  \/\/ PutEgg \u653e\u9e21\u86cb\n  PutEgg(num int)\n  \/\/ PutWafer \u653e\u8584\u8106\n  PutWafer()\n  \/\/ PutFlavour \u653e\u8c03\u6599 Coriander\u9999\u83dc\uff0cShallot\u8471 Sauce\u9171\n  PutFlavour(hasCoriander, hasShallot, hasSauce bool)\n  \/\/ Build \u644a\u714e\u997c\n  Build() *Pancake\n}\n\n\/\/ Pancake  \u714e\u997c\ntype Pancake struct {\n  pasteQuantity Quantity \/\/ \u9762\u7cca\u5206\u91cf\n  eggNum        int      \/\/ \u9e21\u86cb\u6570\u91cf\n  wafer         string   \/\/ \u8584\u8106\n  hasCoriander  bool     \/\/ \u662f\u5426\u653e\u9999\u83dc\n  hasShallot    bool     \/\/ \u662f\u5426\u653e\u8471\n  hasSauce      bool     \/\/ \u662f\u5426\u653e\u9171\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<p>\u6b63\u5e38\u714e\u997c\u521b\u5efa\u5668<\/p>\n<pre><code>package builder\n\ntype normalPancakeBuilder struct {\n  pasteQuantity Quantity \/\/ \u9762\u7cca\u91cf\n  eggNum        int      \/\/ \u9e21\u86cb\u6570\u91cf\n  friedWafer    string   \/\/ \u6cb9\u70b8\u8584\u8106\n  hasCoriander  bool     \/\/ \u662f\u5426\u653e\u9999\u83dc\n  hasShallot    bool     \/\/ \u662f\u5426\u653e\u8471\n  hasHotSauce   bool     \/\/ \u662f\u5426\u653e\u8fa3\u5473\u9171\n}\n\nfunc NewNormalPancakeBuilder() *normalPancakeBuilder {\n  return &amp;normalPancakeBuilder{}\n}\n\nfunc (n *normalPancakeBuilder) PutPaste(quantity Quantity) {\n  n.pasteQuantity = quantity\n}\n\nfunc (n *normalPancakeBuilder) PutEgg(num int) {\n  n.eggNum = num\n}\n\nfunc (n *normalPancakeBuilder) PutWafer() {\n  n.friedWafer = &quot;\u6cb9\u70b8\u7684\u8584\u8106&quot;\n}\n\nfunc (n *normalPancakeBuilder) PutFlavour(hasCoriander, hasShallot, hasSauce bool) {\n  n.hasCoriander = hasCoriander\n  n.hasShallot = hasShallot\n  n.hasHotSauce = hasSauce\n}\n\nfunc (n *normalPancakeBuilder) Build() *Pancake {\n  return &amp;Pancake{\n    pasteQuantity: n.pasteQuantity,\n    eggNum:        n.eggNum,\n    wafer:         n.friedWafer,\n    hasCoriander:  n.hasCoriander,\n    hasShallot:    n.hasShallot,\n    hasSauce:      n.hasHotSauce,\n  }\n}<\/code><\/pre>\n<p>\u5065\u5eb7\u714e\u997c\u521b\u5efa\u5668<\/p>\n<pre><code>package builder\n\ntype healthyPancakeBuilder struct {\n  milletPasteQuantity Quantity \/\/ \u5c0f\u7c73\u9762\u7cca\u91cf\n  chaiEggNum          int      \/\/ \u67f4\u9e21\u86cb\u6570\u91cf\n  nonFriedWafer       string   \/\/ \u975e\u6cb9\u70b8\u8584\u8106\n  hasCoriander        bool     \/\/ \u662f\u5426\u653e\u9999\u83dc\n  hasShallot          bool     \/\/ \u662f\u5426\u653e\u8471\n}\n\nfunc NewHealthyPancakeBuilder() *healthyPancakeBuilder {\n  return &amp;healthyPancakeBuilder{}\n}\n\nfunc (n *healthyPancakeBuilder) PutPaste(quantity Quantity) {\n  n.milletPasteQuantity = quantity\n}\n\nfunc (n *healthyPancakeBuilder) PutEgg(num int) {\n  n.chaiEggNum = num\n}\n\nfunc (n *healthyPancakeBuilder) PutWafer() {\n  n.nonFriedWafer = &quot;\u975e\u6cb9\u70b8\u7684\u8584\u8106&quot;\n}\n\nfunc (n *healthyPancakeBuilder) PutFlavour(hasCoriander, hasShallot, _ bool) {\n  n.hasCoriander = hasCoriander\n  n.hasShallot = hasShallot\n}\n\nfunc (n *healthyPancakeBuilder) Build() *Pancake {\n  return &amp;Pancake{\n    pasteQuantity: n.milletPasteQuantity,\n    eggNum:        n.chaiEggNum,\n    wafer:         n.nonFriedWafer,\n    hasCoriander:  n.hasCoriander,\n    hasShallot:    n.hasShallot,\n    hasSauce:      false,\n  }\n}<\/code><\/pre>\n<p>\u714e\u997c\u751f\u6210\u5668\u7684\u5c01\u88c5\u7c7b-\u53a8\u5e08<\/p>\n<pre><code>package builder\n\n\/\/ PancakeCook \u644a\u714e\u997c\u5e08\u5085\ntype PancakeCook struct {\n  builder PancakeBuilder\n}\n\nfunc NewPancakeCook(builder PancakeBuilder) *PancakeCook {\n  return &amp;PancakeCook{\n    builder: builder,\n  }\n}\n\n\/\/ SetPancakeBuilder \u91cd\u65b0\u8bbe\u7f6e\u714e\u997c\u6784\u9020\u5668\nfunc (p *PancakeCook) SetPancakeBuilder(builder PancakeBuilder) {\n  p.builder = builder\n}\n\n\/\/ MakePancake \u644a\u4e00\u4e2a\u4e00\u822c\u714e\u997c\nfunc (p *PancakeCook) MakePancake() *Pancake {\n  p.builder.PutPaste(Middle)\n  p.builder.PutEgg(1)\n  p.builder.PutWafer()\n  p.builder.PutFlavour(true, true, true)\n  return p.builder.Build()\n}\n\n\/\/ MakeBigPancake \u644a\u4e00\u4e2a\u5de8\u65e0\u9738\u714e\u997c\nfunc (p *PancakeCook) MakeBigPancake() *Pancake {\n  p.builder.PutPaste(Large)\n  p.builder.PutEgg(3)\n  p.builder.PutWafer()\n  p.builder.PutFlavour(true, true, true)\n  return p.builder.Build()\n}\n\n\/\/ MakePancakeForFlavour \u644a\u4e00\u4e2a\u81ea\u9009\u8c03\u6599\u9738\u714e\u997c\nfunc (p *PancakeCook) MakePancakeForFlavour(hasCoriander, hasShallot, hasSauce bool) *Pancake {\n  p.builder.PutPaste(Large)\n  p.builder.PutEgg(3)\n  p.builder.PutWafer()\n  p.builder.PutFlavour(hasCoriander, hasShallot, hasSauce)\n  return p.builder.Build()\n}<\/code><\/pre>\n<ul>\n<li><strong>\u8fd0\u7528<\/strong><\/li>\n<\/ul>\n<pre><code>package builder\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestBuilder(t *testing.T) {\n  pancakeCook := NewPancakeCook(NewNormalPancakeBuilder())\n  fmt.Printf(&quot;\u644a\u4e00\u4e2a\u666e\u901a\u714e\u997c %#v\/n&quot;, pancakeCook.MakePancake())\n\n  pancakeCook.SetPancakeBuilder(NewHealthyPancakeBuilder())\n  fmt.Printf(&quot;\u644a\u4e00\u4e2a\u5065\u5eb7\u7684\u52a0\u91cf\u714e\u997c %#v\/n&quot;, pancakeCook.MakeBigPancake())\n}<\/code><\/pre>\n<p>\u8f93\u51fa<\/p>\n<pre><code>=== RUN   TestBuilder\n\u644a\u4e00\u4e2a\u666e\u901a\u714e\u997c &amp;builder.Pancake{pasteQuantity:5, eggNum:1, wafer:&quot;\u6cb9\u70b8\u7684\u8584\u8106&quot;, hasCoriander:true, hasShallot:true, hasSauce:true}\n\u644a\u4e00\u4e2a\u5065\u5eb7\u7684\u52a0\u91cf\u714e\u997c &amp;builder.Pancake{pasteQuantity:10, eggNum:3, wafer:&quot;\u975e\u6cb9\u70b8\u7684\u8584\u8106&quot;, hasCoriander:true, hasShallot:true, hasSauce:false}\n--- PASS: TestBuilder (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916598\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u539f\u578b\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>\uff08\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u539f\u578b\u662f\u4e00\u79cd\u521b\u5efa\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u4f7f\u4f60\u80fd\u591f\u590d\u5236\u5bf9\u8c61\uff0c\u751a\u81f3\u662f\u590d\u6742\u5bf9\u8c61\uff0c\u800c\u53c8\u65e0\u9700\u4f7f\u4ee3\u7801\u4f9d\u8d56\u5b83\u4eec\u6240\u5c5e\u7684\u7c7b\u3002<\/p>\n<p>\u6240\u6709\u7684\u539f\u578b\u7c7b\u90fd\u5fc5\u987b\u6709\u4e00\u4e2a\u901a\u7528\u7684\u63a5\u53e3\uff0c \u4f7f\u5f97\u5373\u4f7f\u5728\u5bf9\u8c61\u6240\u5c5e\u7684\u5177\u4f53\u7c7b\u672a\u77e5\u7684\u60c5\u51b5\u4e0b\u4e5f\u80fd\u590d\u5236\u5bf9\u8c61\u3002\u539f\u578b\u5bf9\u8c61\u53ef\u4ee5\u751f\u6210\u81ea\u8eab\u7684\u5b8c\u6574\u526f\u672c\uff0c \u56e0\u4e3a\u76f8\u540c\u7c7b\u7684\u5bf9\u8c61\u53ef\u4ee5\u76f8\u4e92\u8bbf\u95ee\u5bf9\u65b9\u7684\u79c1\u6709\u6210\u5458\u53d8\u91cf\u3002<\/p>\n<h3><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong><\/h3>\n<p>\u7eb8\u8d28\u6587\u4ef6\u53ef\u4ee5\u901a\u8fc7\u590d\u5370\u673a\u8f7b\u677e\u62f7\u8d1d\u51fa\u591a\u4efd\uff0c\u8bbe\u7f6ePaper\u63a5\u53e3\uff0c\u5305\u542b\u8bfb\u53d6\u6587\u4ef6\u5185\u5bb9\u548c\u514b\u9686\u6587\u4ef6\u4e24\u4e2a\u65b9\u6cd5\u3002\u540c\u65f6\u58f0\u660e\u4e24\u4e2a\u7c7b\u62a5\u7eb8\uff08Newspaper\uff09\u548c\u7b80\u5386\uff08Resume\uff09\u5b9e\u73b0\u4e86Paper\u63a5\u53e3\uff0c\u901a\u8fc7\u590d\u5370\u673a\uff08Copier\uff09\u590d\u5370\u51fa\u4e24\u7c7b\u6587\u4ef6\u7684\u526f\u672c\uff0c\u5e76\u8bfb\u53d6\u6587\u4ef6\u526f\u672c\u5185\u5bb9\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u63a5\u53e3\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package prototype\n\nimport (\n  &quot;bytes&quot;\n  &quot;fmt&quot;\n  &quot;io&quot;\n)\n\n\/\/ Paper \u7eb8\u5f20\uff0c\u5305\u542b\u8bfb\u53d6\u5185\u5bb9\u7684\u65b9\u6cd5\uff0c\u62f7\u8d1d\u7eb8\u5f20\u7684\u65b9\u6cd5\uff0c\u4f5c\u4e3a\u539f\u578b\u6a21\u5f0f\u63a5\u53e3\ntype Paper interface {\n  io.Reader\n  Clone() Paper\n}\n\n\/\/ Newspaper \u62a5\u7eb8 \u5b9e\u73b0\u539f\u578b\u63a5\u53e3\ntype Newspaper struct {\n  headline string\n  content  string\n}\n\nfunc NewNewspaper(headline string, content string) *Newspaper {\n  return &amp;Newspaper{\n    headline: headline,\n    content:  content,\n  }\n}\n\nfunc (np *Newspaper) Read(p []byte) (n int, err error) {\n  buf := bytes.NewBufferString(fmt.Sprintf(&quot;headline:%s,content:%s&quot;, np.headline, np.content))\n  return buf.Read(p)\n}\n\nfunc (np *Newspaper) Clone() Paper {\n  return &amp;Newspaper{\n    headline: np.headline + &quot;_copied&quot;,\n    content:  np.content,\n  }\n}\n\n\/\/ Resume \u7b80\u5386 \u5b9e\u73b0\u539f\u578b\u63a5\u53e3\ntype Resume struct {\n  name       string\n  age        int\n  experience string\n}\n\nfunc NewResume(name string, age int, experience string) *Resume {\n  return &amp;Resume{\n    name:       name,\n    age:        age,\n    experience: experience,\n  }\n}\n\nfunc (r *Resume) Read(p []byte) (n int, err error) {\n  buf := bytes.NewBufferString(fmt.Sprintf(&quot;name:%s,age:%d,experience:%s&quot;, r.name, r.age, r.experience))\n  return buf.Read(p)\n}\n\nfunc (r *Resume) Clone() Paper {\n  return &amp;Resume{\n    name:       r.name + &quot;_copied&quot;,\n    age:        r.age,\n    experience: r.experience,\n  }\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u7528<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package prototype\n\nimport (\n  &quot;fmt&quot;\n  &quot;reflect&quot;\n  &quot;testing&quot;\n)\n\nfunc TestPrototype(t *testing.T) {\n  copier := NewCopier(&quot;\u4e91\u6253\u5370\u673a&quot;)\n  oneNewspaper := NewNewspaper(&quot;Go\u662f\u6700\u597d\u7684\u7f16\u7a0b\u8bed\u8a00&quot;, &quot;Go\u8bed\u8a00\u5341\u5927\u4f18\u52bf&quot;)\n  oneResume := NewResume(&quot;\u5c0f\u660e&quot;, 29, &quot;5\u5e74\u7801\u519c&quot;)\n\n  otherNewspaper := copier.copy(oneNewspaper)\n  copyNewspaperMsg := make([]byte, 100)\n  byteSize, _ := otherNewspaper.Read(copyNewspaperMsg)\n  fmt.Println(&quot;copyNewspaperMsg:&quot; + string(copyNewspaperMsg[:byteSize]))\n\n  otherResume := copier.copy(oneResume)\n  copyResumeMsg := make([]byte, 100)\n  byteSize, _ = otherResume.Read(copyResumeMsg)\n  fmt.Println(&quot;copyResumeMsg:&quot; + string(copyResumeMsg[:byteSize]))\n}\n\n\/\/ Copier \u590d\u5370\u673a\ntype Copier struct {\n  name string\n}\n\nfunc NewCopier(n string) *Copier {\n  return &amp;Copier{name: n}\n}\n\nfunc (c *Copier) copy(paper Paper) Paper {\n  fmt.Printf(&quot;copier name:%v is copying:%v &quot;, c.name, reflect.TypeOf(paper).String())\n  return paper.Clone()\n}<\/code><\/pre>\n<p>\u8f93\u51fa<\/p>\n<pre><code>=== RUN   TestPrototype\ncopier name:\u4e91\u6253\u5370\u673a is copying:*prototype.Newspaper copyNewspaperMsg:headline:Go\u662f\u6700\u597d\u7684\u7f16\u7a0b\u8bed\u8a00_copied,content:Go\u8bed\u8a00\u5341\u5927\u4f18\u52bf\ncopier name:\u4e91\u6253\u5370\u673a is copying:*prototype.Resume copyResumeMsg:name:\u5c0f\u660e_copied,age:29,experience:5\u5e74\u7801\u519c\n--- PASS: TestPrototype (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916599\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2><strong>\u5355\u4f8b\u6a21\u5f0f<\/strong><\/h2>\n<h3><strong>(\u4e00\uff09\u6982\u5ff5<\/strong><\/h3>\n<p>\u5355\u4f8b\u662f\u4e00\u79cd\u521b\u5efa\u578b\u8bbe\u8ba1\u6a21\u5f0f\uff0c\u8ba9\u4f60\u80fd\u591f\u4fdd\u8bc1\u4e00\u4e2a\u7c7b\u53ea\u6709\u4e00\u4e2a\u5b9e\u4f8b\uff0c\u5e76\u63d0\u4f9b\u4e00\u4e2a\u8bbf\u95ee\u8be5\u5b9e\u4f8b\u7684\u5168\u5c40\u8282\u70b9\u3002<\/p>\n<p>\u5355\u4f8b\u62e5\u6709\u4e0e\u5168\u5c40\u53d8\u91cf\u76f8\u540c\u7684\u4f18\u7f3a\u70b9\u3002\u5c3d\u7ba1\u5b83\u4eec\u975e\u5e38\u6709\u7528\uff0c\u4f46\u5374\u4f1a\u7834\u574f\u4ee3\u7801\u7684\u6a21\u5757\u5316\u7279\u6027\u3002<\/p>\n<p><strong>\uff08\u4e8c\uff09\u793a\u4f8b<\/strong>  <\/p>\n<p>\u901a\u8fc7\u5730\u7403\u5bf9\u8c61\u5b9e\u73b0\u5355\u4f8b\uff0cearth\u4e0d\u80fd\u5bfc\u51fa\uff0c\u901a\u8fc7TheEarth\u65b9\u6cd5\u8bbf\u95ee\u5168\u5c40\u552f\u4e00\u5b9e\u4f8b\uff0c\u5e76\u901a\u8fc7sync.Once\u5b9e\u73b0\u591a\u534f\u7a0b\u4e0b\u4e00\u6b21\u52a0\u8f7d\u3002<\/p>\n<ul>\n<li>\n<h4><strong>\u63a5\u53e3\u5b9e\u73b0<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package singleton\n\nimport &quot;sync&quot;\n\nvar once sync.Once\n\n\/\/ \u4e0d\u53ef\u5bfc\u51fa\u5bf9\u8c61\ntype earth struct {\n  desc string\n}\n\nfunc (e *earth) String() string {\n  return e.desc\n}\n\n\/\/ theEarth \u5730\u7403\u5355\u5b9e\u4f8b\nvar theEarth *earth\n\n\/\/ TheEarth \u83b7\u53d6\u5730\u7403\u5355\u5b9e\u4f8b\nfunc TheEarth() *earth {\n  if theEarth == nil {\n    once.Do(func() {\n      theEarth = &amp;earth{\n        desc: &quot;\u7f8e\u4e3d\u7684\u5730\u7403\uff0c\u5b55\u80b2\u4e86\u751f\u547d\u3002&quot;,\n      }\n    })\n  }\n  return theEarth\n}<\/code><\/pre>\n<ul>\n<li>\n<h4><strong>\u8fd0\u7528<\/strong><\/h4>\n<\/li>\n<\/ul>\n<pre><code>package singleton\n\nimport (\n  &quot;fmt&quot;\n  &quot;testing&quot;\n)\n\nfunc TestSingleton(t *testing.T) {\n  fmt.Println(TheEarth().String())\n}<\/code><\/pre>\n<p>\u8f93\u51fa<\/p>\n<pre><code>=== RUN   TestSingleton\n\u7f8e\u4e3d\u7684\u5730\u7403\uff0c\u5b55\u80b2\u4e86\u751f\u547d\u3002\n--- PASS: TestSingleton (0.00s)\nPASS<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042916600\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042916584\">https:\/\/segmentfault.com\/a\/1190000042916584<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5bfc\u8bed| \u7ee7\u4e0a\u7bc7\u3010\u5feb\u6536\u85cf\uff01\u6700\u5168GO\u8bed\u8a00\u5b9e\u73b0\u8bbe\u8ba1\u6a21\u5f0f\u3011\uff0c\u672c\u6587\u7ee7\u7eed\u5217\u51faGO\u8bed\u8a00\u5b9e\u73b0\u7684\u7ecf\u5178\u8bbe\u8ba1\u6a21\u5f0f\u793a\u4f8b\uff0c\u6bcf\u4e2a\u793a\u4f8b\u90fd\u7cbe\u5fc3 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10006923","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006923","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006923"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006923\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}