<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>设计模式 on 冯威的博客</title><link>https://fwhyy.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/</link><description>Recent content in 设计模式 on 冯威的博客</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Mon, 13 Dec 2021 08:05:00 +0800</lastBuildDate><atom:link href="https://fwhyy.com/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/atom.xml" rel="self" type="application/rss+xml"/><item><title>设计模式：面向对象的设计原则下（ISP、DIP、KISS、YAGNI、DRY、LOD）</title><link>https://fwhyy.com/2021/12/object-oriented-design-principles-2/</link><pubDate>Mon, 13 Dec 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/12/object-oriented-design-principles-2/</guid><description>&lt;p&gt;本文继续来介绍接口隔离原则（ISP）和依赖倒置原则（DIP），这两个原则都和接口和继承有关。文章最后会简单介绍几个除了 SOLID 原则之外的原则。&lt;/p&gt;</description></item><item><title>设计模式：面向对象的设计原则上（SRP、OCP、LSP）</title><link>https://fwhyy.com/2021/12/object-oriented-design-principles-1/</link><pubDate>Mon, 06 Dec 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/12/object-oriented-design-principles-1/</guid><description>&lt;p&gt;在面向对象的世界里，可以分为：面向对象的基础知识、面向对象的设计原则和设计模式，如果用武侠小说来做比喻，基础知识就是需要练习的基本功、设计原则就是内功心法、设计模式则是各种各样的具体招式，所以说熟练掌握了设计原则，就能以不变应万变。&lt;/p&gt;</description></item><item><title>设计模式：面向对象的基础知识</title><link>https://fwhyy.com/2021/11/object-oriented-basic-knowledge/</link><pubDate>Mon, 15 Nov 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/11/object-oriented-basic-knowledge/</guid><description>&lt;p&gt;主流的编程范式有三种：面向过程、面向对象和函数式编程，我们现在使用的主流编程语言 C# 或 Java，都是面向对象语言，所以常常说的设计模式也是在面向对象语言这个前提之下。&lt;/p&gt;
&lt;p&gt;面向对象的基础知识和一些设计原则，我认为是学习设计模式的基础，本文就聊下这些基础知识。&lt;/p&gt;</description></item><item><title>现在还需要学习设计模式吗？</title><link>https://fwhyy.com/2021/11/do-you-still-need-to-learn-design-patterns-now/</link><pubDate>Mon, 01 Nov 2021 08:05:00 +0800</pubDate><guid>https://fwhyy.com/2021/11/do-you-still-need-to-learn-design-patterns-now/</guid><description>&lt;p&gt;最近面试了不少人，Java 和 dotNET 的都有，当问到设计模式时，大部分都只能说出单例和工厂，有些能聊聊其他的一些模式的，大多也没有在实际项目中用过。为了团队成员能有更好的编码能力，便有了重新写写设计模式的想法，写作也是一个重新学习的过程。&lt;/p&gt;</description></item><item><title>设计模式笔记(25)—总结</title><link>https://fwhyy.com/2010/02/design-patterns-notes-25-summary/</link><pubDate>Wed, 03 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/design-patterns-notes-25-summary/</guid><description>&lt;p&gt;断断续续经历了几个月的时间将WebCast的设计模式讲座重新完整听了一遍，并做了笔记，才有了这个设计模式笔记系列，本系列的文章大部分只是给出了基本代码的实现，而并没有去衍生其他的一些例子，笔者认为通过基本的代码实现就能够了解到模式的应用场景，弄出些花哨的例子反倒会让人眼花缭乱，可能并达不到预期的效果，毕竟在实际的应用中我们不是去套用模式。本文作为该系列的最后一篇，将对设计模式做个总结。&lt;/p&gt;
&lt;p&gt;首先看下创建型、结构型、行为型这三种类型的模式的解释&lt;/p&gt;
&lt;h2 id="创建型"&gt;创建型&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Singleton模式解决的是实体对象个数的问题。除了Singleton之外，其他创建型模式解决的都是new所带来的耦合关系。&lt;/li&gt;
&lt;li&gt;Factory Method, Abstract Factory, Builder都需要一个额外的工厂类来负责实例化“易变对象”，而 Prototype则是通过原型 （一个特殊的工厂类）来克隆“易变对象”。&lt;/li&gt;
&lt;li&gt;如果遇到“易变类”，起初的设计通常从FactoryMethod开始，当遇到更多的复杂变化时，再考虑重构为其他三种工厂模式 （Abstract Factory 、Builder 、Prototype ）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="结构型"&gt;结构型&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Adapter模式注重转换接口，将不吻合的接口适配对接。&lt;/li&gt;
&lt;li&gt;Bridge模式注重分离接口与其实现，支持多维度变化。&lt;/li&gt;
&lt;li&gt;Composite模式注重统一接口，将“一对多”的关系转化为“一对一”的关系。&lt;/li&gt;
&lt;li&gt;Decorator模式注重稳定接口，在此前提下为对象扩展功能。&lt;/li&gt;
&lt;li&gt;Façade模式注重简化接口，简化组件系统与外部客户程序的依赖关系。&lt;/li&gt;
&lt;li&gt;Flyweight 模式注重保留接口，在内部使用共享技术对对象存储进行优化。&lt;/li&gt;
&lt;li&gt;Proxy 模式注重假借接口，增加间接层来实现灵活控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="行为型"&gt;行为型&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Template Method模式封装算法结构，支持算法子步骤变化。&lt;/li&gt;
&lt;li&gt;Strategy模式注重封装算法，支持算法的变化。&lt;/li&gt;
&lt;li&gt;State模式注重封装与状态相关的行为，支持状态的变化。&lt;/li&gt;
&lt;li&gt;Memento模式注重封装对象状态变化，支持状态保存/恢复。&lt;/li&gt;
&lt;li&gt;Mediator模式注重封装对象间的交互，支持对象交互的变化。&lt;/li&gt;
&lt;li&gt;Chain Of Responsibility模式注重封装对象责任，支持责任的变化。&lt;/li&gt;
&lt;li&gt;Command模式注重将请求封装为对象，支持请求的变化。&lt;/li&gt;
&lt;li&gt;Iterator 模式注重封装集合对象内部结构，支持集合的变化。&lt;/li&gt;
&lt;li&gt;Interpreter模式注重封装特定领域变化，支持领域问题的频繁变化。&lt;/li&gt;
&lt;li&gt;Observer模式注重封装对象通知，支持通信对象的变化。&lt;/li&gt;
&lt;li&gt;Visitor模式注重封装对象操作变化，支持在运行时为类层次结构动态添加新的操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="设计模式应用总结"&gt;设计模式应用总结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;设计模式建立在对系统变化点的基础上进行，哪里有变化点，哪里应用设计模式。&lt;/li&gt;
&lt;li&gt;设计模式应该以演化的方式来获得，系统的变化点往往是经过不断演化才能准确定位。&lt;/li&gt;
&lt;li&gt;不能为了模式而模式，设计模式是一种软件设计的软力量，而非规范标准。不应夸大设计模式的作用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面的大部分内容都为讲座中的内容，并没有做更多的改动，因为那些概况已经非常简明扼要。软件发展到今天，可以说远远不止这23中模式，只是常常被大家所提及的是这23中经典而已。这些模式的提出时因为软件的需求总是在发生变化，如果说不存在需求的变化，那么设计模式也就没有存在的必要了。这种情况是不可能存在，所以为了在需求变化的时候能够很好的应对，提供代码复用，降低成本就需要应用设计模式。所以说设计模式并不是在软件设计之初就存在，而是随着需求的变化一步一步重构而来的。&lt;/p&gt;
&lt;p&gt;设计模式虽然很多，但万变不离其宗，不管怎么变都脱离不了5大设计原则（SRP OCP LSP DIP ISP），掌握了这五大设计原则，勤思考多实践，那么在项目中遇到变化时就可以灵活运行设计模式了。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(24)—访问者模式（行为型）</title><link>https://fwhyy.com/2010/02/design-patterns-notes-24-visitor-pattern/</link><pubDate>Tue, 02 Feb 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/02/design-patterns-notes-24-visitor-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;表示一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，由于需求的改变，某些类层次结构中常常需要增加新的行为（方法），如果直接在基类中做这样的更改，将会给子类带来很繁重的变更负担，甚至破坏原有设计。如何在不更改类层次结构的前提下，在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作，从而避免上述问题？请看下面访问者模式结构图和代码。&lt;/p&gt;
&lt;p&gt;访问者模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290611525.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;基本代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 声明了一个或多个需要添加的操作
/// &amp;lt;/summary&amp;gt;
public abstract class Visitor
{
 public abstract void VisitorConcreteElementA(ConcreteElementA concreteElementA);
 public abstract void VisitorConcreteElementB(ConcreteElementB concreteElementB);
}
/// &amp;lt;summary&amp;gt;
/// 操作的具体类1
/// &amp;lt;/summary&amp;gt;
public class ConcreteVisitor1:Visitor
{
 public override void VisitorConcreteElementA(ConcreteElementA concreteElementA)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementA.GetType().Name);
 }
 public override void VisitorConcreteElementB(ConcreteElementB concreteElementB)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementB.GetType().Name);
 }
}
/// &amp;lt;summary&amp;gt;
/// 操作的具体类2
/// &amp;lt;/summary&amp;gt;
public class ConcreteVisitor2 : Visitor
{
 public override void VisitorConcreteElementA(ConcreteElementA concreteElementA)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementA.GetType().Name);
 }
 public override void VisitorConcreteElementB(ConcreteElementB concreteElementB)
 {
 Console.WriteLine(&amp;#34;{0}访问{1}&amp;#34;, this.GetType().Name, concreteElementB.GetType().Name);
 }
}
/// &amp;lt;summary&amp;gt;
/// 接受Visitor并使用其操作的抽象类
/// &amp;lt;/summary&amp;gt;
public abstract class Element
{
 public abstract void Accept(Visitor visitor);
}
/// &amp;lt;summary&amp;gt;
/// 接受Visitor并使用其操作的具体类
/// &amp;lt;/summary&amp;gt;
public class ConcreteElementA : Element
{
 public override void Accept(Visitor visitor)
 {
 visitor.VisitorConcreteElementA(this);
 }
 public void OperationA() { }
}
/// &amp;lt;summary&amp;gt;
/// 接受Visitor并使用其操作的具体类
/// &amp;lt;/summary&amp;gt;
public class ConcreteElementB : Element
{
 public override void Accept(Visitor visitor)
 {
 visitor.VisitorConcreteElementB(this);
 }
 public void OperationB() { }
}
public class ObjectStructure
{
 private List&amp;lt;Element&amp;gt; list = new List&amp;lt;Element&amp;gt;();
 public void Add(Element element)
 {
 list.Add(element);
 }
 public void Del(Element element)
 {
 if(list.Contains(element))
 list.Remove(element);
 }
 public void Accept(Visitor visitor)
 {
 foreach (Element e in list)
 {
 e.Accept(visitor);
 }
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端代码
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 ObjectStructure os = new ObjectStructure();
 os.Add(new ConcreteElementA());
 os.Add(new ConcreteElementB());
 Visitor cv1 = new ConcreteVisitor1();
 Visitor cv2 = new ConcreteVisitor2();
 os.Accept(cv2);
 os.Accept(cv1);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="visitor模式的几个要点"&gt;Visitor模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Visitor模式通过所谓双重分发（double dispatch）来实现在不更改Element类层次结构的前提下，在运行时透明地为类层次结构上的各个类动态添加新的操作。&lt;/li&gt;
&lt;li&gt;Visitor模式通过所谓双重分发（double dispatch）来实现在不更改Element类层次结构的前提下，在运行时透明地为类层次结构上的各个类动态添加新的操作。&lt;/li&gt;
&lt;li&gt;Visitor模式的最大缺点在于扩展类层次结构（增添新的Element子类），会导致Visitor类的改变。因此Vistor模式适用于“Element类层次结构稳定，而其中的操作却经常面临频繁改动”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(23)—策略者模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-23-strategy-pattern/</link><pubDate>Sun, 31 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-23-strategy-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义一系列算法，把它们一个个封装起来，并且使它们可互相替换。该模式使得算法可独立于使用它的客 户而变化。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，某些对象使用的算法可能多种多样，经常改变，如果将这些算法都编码到对象中，将会使对象变得异常复杂；而且有时候支持不使用的算法也是一个性能负担。如何在运行时根据需要透明地更改对象的算法？将算法与对象本身解耦，从而避免上述问题？看下面的策略者模式的结构图和基本代码，策略者模式比较简单，下面只是给出基本的代码实现。&lt;/p&gt;
&lt;p&gt;策略者模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290610502.webp" alt="image-20220129061002254" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;基本实现代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象算法类
/// &amp;lt;/summary&amp;gt;
public abstract class Strategy
{
 //抽象算法方法
 public abstract void AlgorithmInterface();
}
/// &amp;lt;summary&amp;gt;
/// 具体算法A
/// &amp;lt;/summary&amp;gt;
public class ConcretestrategyA : Strategy
{
 public override void AlgorithmInterface()
 {
 Console.WriteLine(&amp;#34;算法A的实现&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体算法B
/// &amp;lt;/summary&amp;gt;
public class ConcretestrategyB : Strategy
{
 public override void AlgorithmInterface()
 {
 Console.WriteLine(&amp;#34;算法B的实现&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体算法C
/// &amp;lt;/summary&amp;gt;
public class ConcretestrategyC : Strategy
{
 public override void AlgorithmInterface()
 {
 Console.WriteLine(&amp;#34;算法C的实现&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 上下文
/// &amp;lt;/summary&amp;gt;
public class Context
{
 private Strategy _strategy;
 public Context(Strategy stragtety)
 {
 this._strategy = stragtety;
 }
 public void ContextInterface()
 {
 _strategy.AlgorithmInterface();
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端代码
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 Context context;
 context = new Context(new ConcretestrategyA());
 context.ContextInterface();
 context = new Context(new ConcretestrategyB());
 context.ContextInterface();
 context = new Context(new ConcretestrategyC());
 context.ContextInterface();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行结果如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(22)—状态模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-22-state-pattern/</link><pubDate>Thu, 28 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-22-state-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，某些对象的状态如果改变，其行为也会随之而发生变化，比如文档处于只读状态，其支持的行为和读写状态支持的行为就可能完全不同。如何在运行时根据对象的状态来透明地更改对象的行为？而不会为对象操作和状态转化之间引入紧耦合？看下面状态模式的结构图和代码。&lt;/p&gt;
&lt;p&gt;状态模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290611919.webp" alt="2010-12-29_110619" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;日常生活中我们常见的灯会有两种状态开和关，当灯亮着时我们可以用开关使之熄灭，反之则变量，看下面的代码就是改变灯的开关状态的一个过程：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 灯的状态开和关
/// &amp;lt;/summary&amp;gt;
public enum LightState
{
 On,
 Off
}
public class ChangeLightState
{
 private LightState _state = LightState.On;
 public LightState Change()
 {
 if (_state == LightState.On)
 {
 _state = LightState.Off;
 }
 else if (_state == LightState.Off)
 {
 _state = LightState.On;
 }
 return _state;
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 ChangeLightState l = new ChangeLightState();
 l.Change();
 l.Change();
 l.Change();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码使用if语句来解决了灯开关状态的问题，不过在实际开发中的一些状态不可能是简单的枚举，这时如果依然使用if语句就会显得比较复杂，而且随着状态的改变会频繁进行修改if语句。所以需要将状态转换和处理的变化封装在抽象后的具体类中，看上面结构图的对应代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class State
{
 public abstract void Handle(Context context);
}
public class ConcreteStateA : State
{
 public override void Handle(Context context)
 {
 context.State = new ConcreteStateB();
 }
}
public class ConcreteStateB : State
{
 public override void Handle(Context context)
 {
 context.State = new ConcreteStateA();
 }
}
public class Context
{
 private State _state;
 public Context(State state)
 {
 this._state = state;
 }
 public State State
 {
 get { return _state; }
 set { _state = value;}
 }
 public void Request()
 {
 _state.Handle(this);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 Context context = new Context(new ConcreteStateA());
 context.Request();
 context.Request();
 context.Request();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;根据状态模式将上面的灯开关的代码改进如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(20)—职责链模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-20-chain-of-responsibility-pattern/</link><pubDate>Wed, 27 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-20-chain-of-responsibility-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;使多个对象都有机会处理请求，从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链，并沿着这条链传递请求，直到有一个对象处理它为止。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，一个请求可能被多个对象处理，但是每个请求在运行时只能有一个接受者，如果显式指定，将必不可少地带来请求发送者与接受者的紧耦合。如何使请求的发送者不需要指定具体的接受者？让请求的接受者自己在运行时决定来处理请求，从而使两者解耦。&lt;/p&gt;
&lt;p&gt;职责链模式结构图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290613054.webp" alt="2010-12-29_111712" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象处理类
/// &amp;lt;/summary&amp;gt;
public abstract class BaseHandler
{
 public BaseHandler(BaseHandler next)
 {
 this.Next = next;
 }
 public BaseHandler Next { get; set; }
 protected abstract bool CanHandleRequest(Request request);
 public virtual void HandleRequest(Request request)
 {
 if (Next != null)
 {
 this.Next.HandleRequest(request);
 }
 }
}
public class AHandler:BaseHandler
{
 public AHandler(BaseHandler next)
 : base(next)
 {

 }
 protected override bool CanHandleRequest(Request request)
 {
 return request.Name == &amp;#34;A&amp;#34;;
 }
 public override void HandleRequest(Request request)
 {
 if (this.CanHandleRequest(request))
 {
 Console.WriteLine(&amp;#34;处理A的请求&amp;#34;);
 }
 else
 {
 base.HandleRequest(request);
 }
 }
}
public class BHandler : BaseHandler
{
 public BHandler(BaseHandler next)
 : base(next)
 {

 }
 protected override bool CanHandleRequest(Request request)
 {
 return request.Name == &amp;#34;B&amp;#34;;
 }
 public override void HandleRequest(Request request)
 {
 if (this.CanHandleRequest(request))
 {
 Console.WriteLine(&amp;#34;处理B的请求&amp;#34;);
 }
 else
 {
 base.HandleRequest(request);
 }
 }
}
public class CHandler : BaseHandler
{
 public CHandler(BaseHandler next)
 : base(next)
 {

 }
 protected override bool CanHandleRequest(Request request)
 {
 return request.Name == &amp;#34;C&amp;#34;;
 }
 public override void HandleRequest(Request request)
 {
 if (this.CanHandleRequest(request))
 {
 Console.WriteLine(&amp;#34;处理C的请求&amp;#34;);
 }
 else
 {
 base.HandleRequest(request);
 }
 }
}
public class Sender
{
 public Request _request;
 public Sender(Request request)
 {
 this._request = request;
 }
 public void Process(BaseHandler handler)
 {
 handler.HandleRequest(_request);
 }
}
/// &amp;lt;summary&amp;gt;
/// 请求的信息类
/// &amp;lt;/summary&amp;gt;
public class Request
{
 public string Name { get; set; }
 public Request(string name)
 {
 this.Name = name;
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 Sender sender = new Sender(new Request(&amp;#34;A&amp;#34;));
 BaseHandler handler1 = new AHandler(null);
 BaseHandler handler2 = new BHandler(handler1);
 BaseHandler handler3 = new CHandler(handler2);
 sender.Process(handler3);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="chain-of-responsibility模式的几个要点"&gt;Chain of Responsibility模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Chain of Responsibility 模式的应用场合在于“一个请求可能有多个接受者，但是最后真正的接受者只有一个”，只有这时候请求发送者与接受者的耦合才有可能出现“变化脆弱”的症状，职责链的目的就是将二者解耦，从而更好地应对变化。&lt;/li&gt;
&lt;li&gt;应用了Chain of Responsibility 模式后，对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理职责。&lt;/li&gt;
&lt;li&gt;如果请求传递到职责链的末尾仍得不到处理，应该有一个合理的缺省机制。这也是每一个接受对象的责任，而不是发出请求的对象的责任&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(21)—备忘录模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-21-memo-pattern/</link><pubDate>Wed, 27 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-21-memo-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，某些对象的状态在转换过程中，可能由于某种需要，要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态，便会暴露对象的细节实现。如何实现对象状态的良好保存与恢复？但同时又不会因此而破坏对象本身的封装性，看下面的结构图和代码。&lt;/p&gt;
&lt;p&gt;备忘录模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290613625.webp" alt="2010-12-29_111357" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中Originator为原发器，也可以讲发起者，可以创建一个备忘录（CreateMemento），Memento为备忘录，负责存储原发器中的内部状态。Caretaker主要负责存储备忘录。代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 备忘录类
/// &amp;lt;/summary&amp;gt;
public class Memento
{
 private string _state;
 public string State
 {
 get{return _state;}
 }
 public Memento(string state)
 {
 this._state = state;
 }
}
/// &amp;lt;summary&amp;gt;
/// 原发器类
/// &amp;lt;/summary&amp;gt;
public class Originator
{
 public string State { get; set; }
 public Memento CreateMemento()
 {
 return new Memento(State);
 }
 public void SetMemento(Memento memento)
 {
 State = memento.State;
 }
}
/// &amp;lt;summary&amp;gt;
/// 管理者
/// &amp;lt;/summary&amp;gt;
public class Caretaker
{
 public Memento Memento { get; set; }
}
/// &amp;lt;summary&amp;gt;
/// 客户端程序
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 //实例化原发器并设置状态名称
 Originator o = new Originator();
 o.State = &amp;#34;oec2003&amp;#34;;
 Console.WriteLine(&amp;#34;设置状态名字为:&amp;#34; + o.State);
 //实例化管理者，创建一个备忘储存在管理者中
 Caretaker c = new Caretaker();
 c.Memento = o.CreateMemento();
 //更改了原发器的状态名称
 o.State = &amp;#34;oec2004&amp;#34;;
 Console.WriteLine(&amp;#34;改后的状态名字为:&amp;#34; + o.State);
 //将备忘信息设置给原发器
 o.SetMemento(c.Memento);
 Console.WriteLine(&amp;#34;原来的状态名字为:&amp;#34; + o.State);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="memento模式的几个要点"&gt;Memento模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;备忘录（Memento）存储原发器（Originator）对象的内部状态，在需要时恢复原发器状态。Memento模式适用于“由原发器管理，却又必须存储在原发器之外的信息”。&lt;/li&gt;
&lt;li&gt;在实现Memento模式中，要防止原发器以外的对象访问备忘录对象。备忘录对象有两个接口，一个为原发器使用的宽接口；一个为其他对象使用的窄接口。&lt;/li&gt;
&lt;li&gt;在实现Memento模式时，要考虑拷贝对象状态的效率问题，如果对象开销比较大，可以采用某种增量式改变来改进Memento模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(19)—观察者模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-19-observer-pattern/</link><pubDate>Mon, 25 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-19-observer-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义对象间的一种一对多的依赖关系，以便当一个对象的状态发生改变时，所有依赖于它的对象都得到通 知并自动更新&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，我们需要为某些对象建立一种“通知依赖关系” ——一个对象（目标对象）的状态发生改变，所有的依赖对象（观察者对象）都将得到通知。如果这样的依赖关系过于紧密，将使软件不能很好地抵御变化。使用面向对象技术，可以将这种依赖关系弱化，并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。&lt;/p&gt;
&lt;p&gt;看这样一个场景，银行的ATM机在处理完成银行账户的存入或取出后会给用户发送手机短信和电子邮件，那么就会有这样三个对象，BankAccount Emailer Mobile，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class BankAccount
{
 Emailer emailer;
 Mobile mobile;
 public void Withdraw(int data)
 {
 //处理存入或取出
 emailer.SendEmail(&amp;#34;&amp;#34;);
 mobile.SendMsg(&amp;#34;&amp;#34;);
 }
}
public class Emailer
{
 public void SendEmail(string to)
 {
 //发送邮件
 }
}
public class Mobile
{
 public void SendMsg(string phoneNumber)
 {
 //发送短信
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码中BankAccount和Emailer Mobile之间有很强的依赖关系，Emailer和Mobile的变化会对BankAccount产生很大的影响，接下来要做的就是使BankAccount不要去依赖Emailer和Mobile这样的具体类，而应该去依赖他们的抽象，抽象的东西通常是稳定的，这样BankAccount和抽象之间的依赖就是一种比较弱的依赖关系，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class UserAccountArgs
{
 public string Email { get; set; }
 public string PhoneNumber { get; set; }
 public UserAccountArgs(string email, string phoneNumer)
 {
 Email = email;
 PhoneNumber = phoneNumer;
 }
}
public interface IAccountObserver
{
 void Update(UserAccountArgs args);
}
public class Emailer : IAccountObserver
{
 public void Update(UserAccountArgs args)
 {
 Console.WriteLine(&amp;#34;消息已发送邮件至邮箱：&amp;#34; + args.Email);
 }
}
public class Mobile : IAccountObserver
{
 public void Update(UserAccountArgs args)
 {
 Console.WriteLine(&amp;#34;消息已发短信至手机：&amp;#34; + args.PhoneNumber);
 }
}
public class BankAccount
{
 List&amp;lt;IAccountObserver&amp;gt; list = new List&amp;lt;IAccountObserver&amp;gt;();
 public void Withdraw(int data)
 {
 //处理存入或取出
 if(data&amp;gt;0)
 {
 Console.WriteLine(&amp;#34;您的账户存入了&amp;#34;+data+&amp;#34;元&amp;#34;);
 }
 else
 {
 Console.WriteLine(&amp;#34;您的账户取出了&amp;#34; + Math.Abs(data) + &amp;#34;元&amp;#34;);
 }
 UserAccountArgs args = 
new UserAccountArgs(&amp;#34;oec2003@gmail.com&amp;#34;,&amp;#34;1388888****&amp;#34;);
 foreach (IAccountObserver observer in list)
 {
 observer.Update(args);
 }
 }
 public void AddObserver(IAccountObserver observer)
 {
 list.Add(observer);
 }
 public void RemoveObserver(IAccountObserver observer)
 {
 list.Remove(observer);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端调用
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 BankAccount bankAccount = new BankAccount();
 bankAccount.AddObserver(new Emailer());
 bankAccount.AddObserver(new Mobile());
 bankAccount.Withdraw(-500);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行结果如下：&lt;/p&gt;</description></item><item><title>设计模式笔记(18)—迭代器模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-18-iterator-pattern/</link><pubDate>Sun, 24 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-18-iterator-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;提供一种方法顺序访问一个聚合对象中的各个元素， 而又不暴露该对象的内部表示。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，集合对象内部结构常常变化各异。但对于这些集合对象，我们希望在不暴露其内部结构的同时，可以让外部客户代码透明地访问其中包含的元素；同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。&lt;/p&gt;</description></item><item><title>设计模式笔记(17)—中介者模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-17-mediator-pattern/</link><pubDate>Wed, 20 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-17-mediator-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，经常会出现多个对象互相关联交互的情况，对象之间常常会维持一种复杂的引用关系，如果遇到一些需求的更改，这种直接的引用关系将面临不断的变化。在这种情况下，我们可使用一个“中介对象”来管理对象间的关联关系，避免相互交互的对象之间的紧耦合引用关系，从而更好地抵御变化。&lt;/p&gt;
&lt;p&gt;中介者模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290617750.webp" alt="2010-12-29_114801" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象的中介者
/// &amp;lt;/summary&amp;gt;
public abstract class Mediator
{
 public abstract void Send(string msg, Colleague colleague);
}
/// &amp;lt;summary&amp;gt;
/// 抽象的同事类
/// &amp;lt;/summary&amp;gt;
public abstract class Colleague
{
 protected Mediator _mediator;
 public Colleague(Mediator mediator)
 {
 _mediator = mediator;
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体的中介者对象
/// &amp;lt;/summary&amp;gt;
public class ConcreteMediator : Mediator
{
 public ConcreteCollegue1 Colleague1 { get; set; }
 public ConcreteCollegue2 Colleague2 { get; set; }
 public override void Send(string msg, Colleague colleague)
 {
 if (colleague == Colleague1)
 {
 Colleague2.Notify(msg);
 }
 else
 {
 Colleague1.Notify(msg);
 }
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体的同事类1
/// &amp;lt;/summary&amp;gt;
public class ConcreteCollegue1:Colleague
{
 public ConcreteCollegue1(Mediator mediator)
 : base(mediator)
 {

 }

 public void Send(string msg)
 {
 _mediator.Send(msg,this);
 }
 public void Notify(string msg)
 {
 Console.WriteLine(&amp;#34;通知同事1：&amp;#34;+msg);
 }
}
/// &amp;lt;summary&amp;gt;
/// 具体的同事类2
/// &amp;lt;/summary&amp;gt;
public class ConcreteCollegue2:Colleague
{
 public ConcreteCollegue2(Mediator mediator)
 : base(mediator)
 {

 }

 public void Send(string msg)
 {
 _mediator.Send(msg,this);
 }
 public void Notify(string msg)
 {
 Console.WriteLine(&amp;#34;通知同事2：&amp;#34;+msg);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户端调用
/// &amp;lt;/summary&amp;gt;
class Program
{
 static void Main(string[] args)
 {
 ConcreteMediator cm = new ConcreteMediator();
 ConcreteCollegue1 cc1 = new ConcreteCollegue1(cm);
 ConcreteCollegue2 cc2 = new ConcreteCollegue2(cm);
 cm.Colleague1 = cc1;
 cm.Colleague2 = cc2;
 cc1.Send(&amp;#34;看阿凡达了吗？&amp;#34;);
 cc2.Send(&amp;#34;呵呵，周末公司组织去看。&amp;#34;);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="mediator模式的几个要点"&gt;Mediator模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;将多个对象间复杂的关联关系解耦，Mediator模式将多个对象间的控制逻辑进行集中管理，变“多个对象互相关联”为“多个对象和一个中介者关联”，简化了系统的维护，抵御了可能的变化。&lt;/li&gt;
&lt;li&gt;随着控制逻辑的复杂化，Mediator具体对象的实现可能相当复杂。这时候可以对Mediator对象进行分解处理。&lt;/li&gt;
&lt;li&gt;Façade模式是解耦系统外到系统内（单向）的对象关联关系；Mediator模式是解耦系统内各个对象之间（双向）的关联关系。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(16)—解释器模式（行为型）</title><link>https://fwhyy.com/2010/01/design-patterns-notes-16-interpreter-pattern/</link><pubDate>Tue, 19 Jan 2010 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2010/01/design-patterns-notes-16-interpreter-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;给定一个语言，定义它的文法的一种表示，并定义一种解释器，这个解释器使用该表示来解释语言中的句 子。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，如果某一特定领域的问题比较复杂，类似的模式不断重复出现，如果使用普通的编程方式来实现将面临非常频繁的变化。在这种情况下，将特定领域的问题表达为某种语法规则下的句子，然后构建一个解释器来解释这样的句子，从而达到解决问题的目的。&lt;/p&gt;
&lt;p&gt;下面看下解释器模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290616838.webp" alt="2010-12-29_115427" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;基本代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 上下文信息
/// &amp;lt;/summary&amp;gt;
public class Context
{
 public string Data { get; set; }
}
/// &amp;lt;summary&amp;gt;
/// 抽象表达式，声明一个抽象的解释操作
/// &amp;lt;/summary&amp;gt;
public abstract class AbstractExpression
{
 public abstract void Interpret(Context context);
}
public class TerminalExpression:AbstractExpression
{
 public override void Interpret(Context context)
 {
 context.Data += &amp;#34;终端,&amp;#34;;
 }
}
public class NonterminalExpression : AbstractExpression
{
 public override void Interpret(Context context)
 {
 context.Data += &amp;#34;非终端,&amp;#34;;
 }
}
public class App
{
 static void Main(string[] args)
 {
 Context context = new Context();
 List&amp;lt;AbstractExpression&amp;gt; list = new List&amp;lt;AbstractExpression&amp;gt;();
 list.Add(new TerminalExpression());
 list.Add(new NonterminalExpression());
 list.Add(new TerminalExpression());

 foreach (AbstractExpression exp in list)
 {
 exp.Interpret(context);
 }
 Console.WriteLine(context.Data);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;接下来看一个实际的应用，功能是数字的转换，如将“五百二十”转换成“520“，首先创建一个Context类用来储存上下文信息，类中有两个属性Statement和Data，分别用来存放汉字的数字和阿拉伯数字。&lt;/p&gt;</description></item><item><title>设计模式笔记(15)—命令模式（行为型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-15-command-pattern/</link><pubDate>Wed, 30 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-15-command-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将一个请求封装为一个对象，从而使你可用不同的请求对客户进行参数化；对请求排队或记录请求日志，以及支持可撤销的操作。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合——比如需
要对行为进行“记录、撤销/重做（undo/redo）、事务”等处理，这种无法抵御变化的紧耦合是不合适的。在这种情况下，如何将“行为请求者”与“行为实现者”解耦？将一组行为抽象为对象，可以实现二者之间的松耦合。&lt;/p&gt;
&lt;p&gt;先来看个反例（版本1），假设在一个应用程序中需要用到要用到很多的一些外部的类，并且要对这些类中的操作进行撤销、记录等操作，如果像下面这样实现就会很乱并且不容易实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Application
{
 public void Process()
 {
 Document doc = new Document();
 doc.ShowText();
 Graphics gra = new Graphics();
 gra.Draw();
 //需要进行undo 记录等操作
 }
}
public class Document
{
 public void ShowText() { }
}
public class Graphics
{
 public void Draw(){ }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;要满足上面提的那些要求就需要用命令模式，命令模式结构图如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290617303.webp" alt="2010-12-29_121609" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;改进后的代码（版本2），将ShowText Draw这种行为抽象起来放到一个接口中，接口命名为ICommand，并且在该接口中还有一个方法签名Undo，用来做撤销处理，当然根据需要还可以加其他的操作。ICommand代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public interface ICommand
{
 void Execute();
 void Undo();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Document类和Graphics类实现该接口，并提供自己的实现，代码如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Document:ICommand
{
 public string Name { get;set;}
 public Document(string name)
 {
 Name = name;
 }
 public void Execute()
 {
 Console.WriteLine(&amp;#34;显示文本 &amp;#34;+Name);
 }
 public void Undo()
 {
 Console.WriteLine(&amp;#34;撤销显示文本 &amp;#34;+Name);
 }
}

public class Graphics : ICommand
{
 public string Name { get;set;}
 public Graphics(string name)
 {
 Name = name;
 }
 public void Execute()
 {
 Console.WriteLine(&amp;#34;画图 &amp;#34;+Name);
 }
 public void Undo()
 {
 Console.WriteLine(&amp;#34;撤销画图 &amp;#34;+Name);
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;客户端调用的代码：&lt;/p&gt;</description></item><item><title>设计模式笔记(14)—模板方法模式（行为型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-14-template-method-pattern/</link><pubDate>Mon, 14 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-14-template-method-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个 算法的结构即可重定义该算法的某些特定步骤。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件构建过程中，对于某一项任务，它常常有稳定的整体操作结构，但各个子步骤却有很多改变的需求，或者由于固有的原因（比如框架与应用之间的关系）而无法和任务的整体结构同时实现。如何在确定稳定操作结构的前提下，来灵活应对各个子步骤的变化或者晚期实现需求？&lt;/p&gt;
&lt;p&gt;模板方法模式结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290615923.webp" alt="2010-12-29_122541" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;AbstractClass类：这个抽象类中定义了一个模板方法TemplateMethod，该方法通常为一个具体方法，将抽象类中的一些抽象的操作组合在其中，推迟到子类实现。&lt;/p&gt;
&lt;p&gt;ConcreteClass类:按照需求实现父类定义的一个或多个抽象方法。&lt;/p&gt;
&lt;p&gt;一个小的例子来反映上面的结构：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 测试车的类---&amp;gt;AbstractClass
/// &amp;lt;/summary&amp;gt;
public abstract class Vehical
{
 protected abstract void Start(); //PrimitiveOperation
 protected abstract void Run(); //PrimitiveOperation
 protected abstract void Trun(); //PrimitiveOperation
 protected abstract void Stop(); //PrimitiveOperation
 /// &amp;lt;summary&amp;gt;
 /// 相当于TemplateMethod
 /// &amp;lt;/summary&amp;gt;
 public void Test()
 {
 //做记录等操作
 Start();
 Run();
 Trun();
 Stop();
 }
}

/// &amp;lt;summary&amp;gt;
/// 红旗车---&amp;gt;ConcreteClass
/// &amp;lt;/summary&amp;gt;
public class HongQiCar : Vehical
{
 protected override void Start()
 {
 Console.WriteLine(&amp;#34;测试红旗车启动&amp;#34;);
 }
 protected override void Run()
 {
 Console.WriteLine(&amp;#34;测试红旗车行驶&amp;#34;);
 }
 protected override void Trun(int degree)
 {
 Console.WriteLine(&amp;#34;测试红旗车转向&amp;#34;);
 }
 protected override void Stop()
 {
 Console.WriteLine(&amp;#34;测试红旗车停止&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// QQ车---&amp;gt;ConcreteClass
/// &amp;lt;/summary&amp;gt;
public class QQCar : Vehical
{
 protected override void Start()
 {
 Console.WriteLine(&amp;#34;测试QQ车启动&amp;#34;);
 }
 protected override void Run()
 {
 Console.WriteLine(&amp;#34;测试QQ车行驶&amp;#34;);
 }
 protected override void Trun(int degree)
 {
 Console.WriteLine(&amp;#34;测试QQ车转向&amp;#34;);
 }
 protected override void Stop()
 {
 Console.WriteLine(&amp;#34;测试QQ车停止&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户代码
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Main()
 {
 Vehical vehical;
 vehical = new HongQiCar();
 vehical.Test();

 vehical = new QQCar();
 vehical.Test();
 Console.ReadLine();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="template-method模式的几个要点"&gt;Template Method模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Template Method模式是一种非常基础性的设计模式，在面向对象系统中有着大量的应用。它用最简洁的机制（虚函数的多态性）为很多应用程序框架提供了灵活的扩展点，是代码复用方面的基本实现结构。&lt;/li&gt;
&lt;li&gt;除了可以灵活应对子步骤的变化外，“不要调用我，让我来调用你”的反向控制结构是Template Method的典型应用。&lt;/li&gt;
&lt;li&gt;在具体实现方面，被Template Method调用的虚方法可以具有实现，也可以没有任何实现（抽象方法、纯虚方法），但一般推荐将它们设置为protected方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(13)—代理模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-13-proxy-pattern/</link><pubDate>Thu, 10 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-13-proxy-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;为其他对象提供一种代理以控制对这个对象的访问。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在面向对象系统中，有些对象由于某种原因（比如对象创建的开销很大，或者某些操作需要安全控制，或者需要进程外的访问等），直接访问会给使用者、或者系统结构带来很多麻烦。如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性？增加一层间接层是软件开发中常见的解决方式。看下结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290619654.webp" alt="2010-12-29_124225" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Subject：该类中定义了一些RealSubject和Proxy中共有的方法。&lt;/p&gt;
&lt;p&gt;RealSubject：这个类是Proxy所要代理的实体类，客户端只和Proxy交互。&lt;/p&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 公共接口
/// &amp;lt;/summary&amp;gt;
interface ISubject
{
 void Request();
}
/// &amp;lt;summary&amp;gt;
/// 被代理的类
/// &amp;lt;/summary&amp;gt;
public class RealSubject : ISubject
{
 public void Request()
 {
 Console.WriteLine(&amp;#34;被代理类的请求&amp;#34;);
 }
}
/// &amp;lt;summary&amp;gt;
/// 代理类
/// &amp;lt;/summary&amp;gt;
public class Proxy : ISubject
{
 RealSubject realSubject=new RealSubject();
 public void Request()
 {
 realSubject.Request();
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户代码
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;#34;args&amp;#34;&amp;gt;&amp;lt;/param&amp;gt;
static void Main(string[] args)
{
 Proxy proxy = new Proxy();
 proxy.Request();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码非常简单，在客户端使用的是Proxy类，其实调用的是RealSubject类中的方法，起到了代理的目的。&lt;/p&gt;
&lt;h2 id="proxy模式的应用场景"&gt;Proxy模式的应用场景&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;远程代理，也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在不同地址空间的事实。（net中的webservice）&lt;/li&gt;
&lt;li&gt;虚拟代理，根据需要创建开销很大的对象。通过他来存放实例化需要很长时间的真实对象。&lt;/li&gt;
&lt;li&gt;安全代理，用来控制真实对象访问时的权限。&lt;/li&gt;
&lt;li&gt;智能指引，指当调用这是对象时，代理处理另外一些事情。
[以上四点摘自《大话设计模式》]&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="proxy模式的几个要点"&gt;Proxy模式的几个要点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;“增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中，直接使用某些对象会带来很多问题，作为间接层的proxy对象便是解决这一问题的常用手段。&lt;/li&gt;
&lt;li&gt;具体proxy设计模式的实现方法、实现粒度都相差很大，有些可能对单个对象做细粒度的控制，如copy-on-write技术，有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。&lt;/li&gt;
&lt;li&gt;Proxy并不一定要求保持接口的一致性，只要能够实现间接控制，有时候损及一些透明性是可以接受的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-1-index/"&gt;返回开篇（索引）&lt;/a&gt;&lt;/p&gt;</description></item><item><title>设计模式笔记(12)—享元模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-12-flyweight-pattern/</link><pubDate>Wed, 09 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-12-flyweight-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;运用共享技术有效地支持大量细粒度的对象。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中，从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时，让外部客户程序仍然能够透明地使用面向对象的方式来进行操作？这需要用到享元模式，不过应用享元模式是需要进行评估的，也就是说在当前情况下是否会对系统造成性能上的影响，如果会那么就是用，下面先来看个小例子是如何进行评估的。&lt;/p&gt;
&lt;p&gt;假设有一个字符的类Charator，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Charator
{
 char c;
 Font f;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;为了方便评估，Charator类中的Font类型采用自定义的类型：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Font
{
 string fontName;
 int size;
 Color color;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在客户代码中使用Charator类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class App
{
 static void Main()
 {
 List&amp;lt;Charator&amp;gt; list=new List&amp;lt;Charator&amp;gt;(100000);
 for (int i = 0; i &amp;lt; list.Count; i++)
 {
 Charator charator = new Charator();
 list.Add(charator);
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在客户代码中将Charator类实例化了100000次，Charator类中有两个成员，并且有个成员为Font类型，Font类型中又定义了三个成员，下面将在代码注释中标出要占用的内存量：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 如果有n个Font对象占用大小为12bytes*n 其实字符串类型
/// 除了本身占用的4bytes外 还有一个引用指针要占用4bytes，
/// 不过这个 不会构成倍乘效应，也就是当有n个对象时不会
/// 以n的倍数增长，所以可以忽略
/// &amp;lt;/summary&amp;gt;
public class Font
{
 string fontName; //4bytes
 int size; //4bytes
 Color color; //4bytes
}
/// &amp;lt;summary&amp;gt;
/// 总共占用2+20+4+8+2=36bytes
/// 第三个的4为指向font的指针
/// 第四个的8为虚表指针和垃圾回收和同步
/// 最后的2为char的填充位
/// &amp;lt;/summary&amp;gt;
public class Charator
{
 /// &amp;lt;summary&amp;gt;
 /// 占用2bytes
 /// &amp;lt;/summary&amp;gt;
 char c;
 /// &amp;lt;summary&amp;gt;
 /// 总占用12bytes+4bytes+4bytes =20bytes
 /// 其中12bytes是三个成员的，另外的两个4bytes分别为
 /// 虚表指针和net垃圾回收机制所需要的一些位，因为每个
 /// 类型最终都可以追溯到object类型，所以默认都会有虚函数
 /// 4byte的虚表指针式不可少的
 /// &amp;lt;/summary&amp;gt;
 Font f; 

}
/// &amp;lt;summary&amp;gt;
/// 36bytes * 100000=3600000bytes =3600k=3.6mb
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Main()
 {
 List&amp;lt;Charator&amp;gt; list=new List&amp;lt;Charator&amp;gt;(100000);
 for (int i = 0; i &amp;lt; list.Count; i++)
 {
 Charator charator = new Charator();
 list.Add(charator);
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码执行会带来3mb多的内存数据，这个对于现在的机器来说算不了什么，上面例子中是做了100000次的计算，那如果再加两个数量级到10000000又会怎么样了，那就会有300多mb，这个数字肯定是不能接受的，那么这个时候就要考虑用享元模式了。 看下面改进后的代码：&lt;/p&gt;</description></item><item><title>设计模式笔记(11)—外观模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-11-appearance-pattern/</link><pubDate>Mon, 07 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-11-appearance-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;为子系统中的一组接口提供一个一致的界面，Façade模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。&lt;/p&gt;
&lt;p&gt;先来看个小例子，假设我们需要开发一个坦克模拟系统用于模拟坦克车在各种作战环境中的行为，其中坦克系统由引擎、控制器、车轮、车身等各子系统构成。就会有下面这些类的产生&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Wheel{ }
public class Engine{ }
public class Controller{ }
public class BodyWork{ }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;不同的场景中的要求都不一样，可能会用到某些子系统，也可能不会用到，这些不同的场景就相当是外部接口，这些场景和子系统的关系如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290618615.webp" alt="2010-12-29_125236" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;图1&lt;/p&gt;
&lt;p&gt;上图中的关系感觉很混乱，场景和子系统之间的耦合度很高，要降低这种耦合度，就要使和场景之间交互的不是这些子系统了，而是相对单一的一个中间层，如下图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290618206.webp" alt="2010-12-29_125304" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;图2&lt;/p&gt;
&lt;p&gt;上图的Facade就将子系统隐藏了，不同的场景都是直接和Facade交互。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;上面图1方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合，随着外部客户程序和各子系统的演化，这种过多的耦合面临很多变化的挑战。如何简化外部客户程序和系统间的交互接口？如何将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦？这就要用到Facade模式，先来看结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290618557.webp" alt="2010-12-29_125333" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;代码实现，先定义一些子系统类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Wheel
{
 public void WAction1() { }
 public void WAction2() { }
}
public class Engine
{
 public void EAction1() { }
 public void EAction2() { }
}
public class Controller
{
 public void CAction1() { }
 public void CAction2() { }
}
public class BodyWork
{
 public void BAction1() { }
 public void BAction2() { }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Facade类，用来组合这些子系统&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class TankFacade
{
 Wheel[] wheels = new Wheel[4];
 Engine[] engines = new Engine[4];
 BodyWork bodywork = new BodyWork();
 Controller controller = new Controller();

 public void Start()
 {
 //用到子系统中的一个或多个
 }
 public void Stop()
 {
 //用到子系统中的一个或多个
 }
 public void Run()
 {
 //用到子系统中的一个或多个
 }
 public void Shot()
 {
 //用到子系统中的一个或多个
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;客户端调用&lt;/p&gt;</description></item><item><title>设计模式笔记(10)—装饰模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-10-decorative-pattern/</link><pubDate>Fri, 04 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-10-decorative-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;动态地给一个对象增加一些额外的职责。就增加功能而言，Decorator模式比生成子类更为灵活。&lt;/p&gt;
&lt;p&gt;首先来看一个小例子，假如我们需要给游戏开发一种坦克，除了各种不同型号的坦克外，还希望在不同的场合来给坦克增加以下的一种或多种功能：比如红外线夜视功能、水陆两栖功能、GPS定位功能等。通常做法如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 抽象坦克
/// &amp;lt;/summary&amp;gt;
public abstract class Tank
{
 public abstract void Shot();
 public abstract void Run();
}

//型号
public class T50 : Tank { }
public class T60 : Tank { }
public class T70 : Tank { }

//在不同场合下的各种功能都抽象为接口，
//如果某种型号的坦克需要某种功能就继承该功能接口
//下面的IA IB IC 为功能A B C的接口
/// &amp;lt;summary&amp;gt;
/// 有A功能的T50型号
/// &amp;lt;/summary&amp;gt;
public class T50A : T50, IA { }
/// &amp;lt;summary&amp;gt;
/// 有A B两种功能的T60型号
/// &amp;lt;/summary&amp;gt;
public class T60AB : T60, IA, IB { }
/// &amp;lt;summary&amp;gt;
/// 有A B C三种功能的T70型号
/// &amp;lt;/summary&amp;gt;
public class T70ABC : T70, IA, IB, IC { }
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;上面描述的问题的根源在于我们“过多地使用了继承来扩展对象的功能”，由于继承为赖幸引入了静态特质，使得这种扩展方式缺乏灵活性，并且随着子类的增多（扩展功能的增多)，各种子类的组合（扩展功能的组合）会导致更多子类的膨胀（多继承）。那么如何使“对象功能的扩展”能够根据需要来动态地实现，同时避免“扩展功能的增多”带来的子类膨胀问题，从而使得任何“功能的变化”所导致的影响减为最低呢？这就需要用到装饰模式（Decorator）。下面先来看下装饰模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201290619381.webp" alt="" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;Component：对应上面例子中的Tank。&lt;/p&gt;
&lt;p&gt;ConcreteComponent：对应坦克的型号 T50 T60 T70等。&lt;/p&gt;
&lt;p&gt;DeCorator ConcreteDecoratorA ConcreteDecoratorB 这三个类就是接下来要实现了。&lt;/p&gt;</description></item><item><title>设计模式笔记(9)—组合模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-9-portfolio-pattern/</link><pubDate>Wed, 02 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-9-portfolio-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将对象组合成树形结构以表示“部分–整体”的层次结构。Composite使得用户对单个对象和组合对象使用具有一致性。&lt;/p&gt;
&lt;p&gt;在面向对象系统中，我们经常会遇到一类具有”容器“特征的对象—即他们在充当对象的同时，又是其他对象的容器。比如在一些管理系统中就会出现总公司下面有很多的分公司，分公司下面有很多的部门，每个部门下又有很多的员工，像分公司和部门就是既充当了“对象”的角色也充当了“容器”的角色；还有我们可能玩过的“俄罗斯套娃”也是这种结构，一个大娃娃里面装个小娃娃，小的里面又有个小的直到最小的一个，中间的娃娃就是既充当了“对象”也充当了“容器”。先看下面这个例子:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;interface IBox
{
 void Process();
}
/// &amp;lt;summary&amp;gt;
/// 相当于树的叶子节点，没有子对象了
/// &amp;lt;/summary&amp;gt;
public class SingleBox : IBox
{
 public void Process()
 { 

 }
}
/// &amp;lt;summary&amp;gt;
/// 容器
/// &amp;lt;/summary&amp;gt;
public class ContainerBox : IBox
{
 List&amp;lt;IBox&amp;gt; list = new List&amp;lt;IBox&amp;gt;();
 public void Process() { }
 public List&amp;lt;IBox&amp;gt; GetBoxes()
 {
 return list;
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户代码
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Mina()
 {
 ///此处从工厂方法中得到盒子的对象，但我们不知道是SingleBox还是ContainerBox
 ///所以要做判断
 IBox box = Factory.Create();
 if (box is ContainerBox)
 {
 box.Process();
 List&amp;lt;IBox&amp;gt; list = ((ContainerBox)box).GetBoxes();
 }
 else if(box is SingleBox)
 {
 box.Process();
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;上面代码的问题的根据在于：客户代码过多地依赖对象容器复杂的内部实现结构，对象容器内部实现结构（而非抽象接口）的变化将引起客户代码的频繁变化，带来了代码的维护性、扩展性等弊端。&lt;/p&gt;
&lt;p&gt;如何将“客户代码与复杂的对象容器结构”解耦？让对象容器自己来实现自身的复杂结构，从而使得客户代码就像处理简单对象一样来处理复杂的对象容器？&lt;/p&gt;
&lt;p&gt;这就要使用Composite模式了，先看下Composite模式的结构图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201281850646.webp" alt="image-20220128185053657" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component：定义了Leaf和Composite的一些共有特性。&lt;/li&gt;
&lt;li&gt;Composite：有容器特征的类型。&lt;/li&gt;
&lt;li&gt;Leaf：叶节点，即一个单独的个体，下面没有子节点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;依据上面的结构图完成代码实现：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class Component
{
 protected string _name;
 public Component(string name)
 {
 _name = name;
 }
 public abstract void Operation();
 public abstract void Add(Component component);
 public abstract void Remove(Component component);
}

public class Leaf : Component
{
 public Leaf(string name) : base(name) { }
 public override void Add(Component component)
 {
 throw new NotSupportedException();
 }
 public override void Remove(Component component)
 {
 throw new NotSupportedException();
 }

 public override void Operation()
 {
 //...do something
 }
}

public class Composite : Component
{
 public Composite(string name):base(name){}
 List&amp;lt;Component&amp;gt; list = new List&amp;lt;Component&amp;gt;();
 /// &amp;lt;summary&amp;gt;
 /// 添加
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;param name=&amp;#34;conponent&amp;#34;&amp;gt;&amp;lt;/param&amp;gt;
 public override void Add(Component component)
 {
 if (list != null)
 {
 list = new List&amp;lt;Component&amp;gt;();
 }
 list.Add(component);
 }
 /// &amp;lt;summary&amp;gt;
 /// 删除
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;param name=&amp;#34;component&amp;#34;&amp;gt;&amp;lt;/param&amp;gt;
 public override void Remove(Component component)
 {
 if (list == null)
 {
 throw new NullReferenceException();
 }
 list.Remove(component);
 }

 public override void Operation()
 {
 if (list != null)
 {
 foreach (Component c in list)
 {
 c.Operation();
 }
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Leaf类为叶子节点类，它的实例是没有子节点的，但是在抽象类中的方法Add和Remove方法必须要实现，按理说这样的实现是没有意义的，所以在此处抛出了NotSupportedException 异常，在客户端调用捕获到再做相应的处理，这种模式称之为“透明足组合模式”，这样做的好处是叶子（Leaf）和容器（Composite）对于外界没有分别，它们具有一致的接口行为。还有一种情况叫“安全组合模式”，在抽象类（Component）中不定义Add Remove方法，而是在容器的实现类中去定义，这样就各司其职了，看下面结构图：&lt;/p&gt;</description></item><item><title>设计模式笔记(8)—桥接模式（结构型）</title><link>https://fwhyy.com/2009/12/design-patterns-notes-8-bridge-pattern/</link><pubDate>Tue, 01 Dec 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/12/design-patterns-notes-8-bridge-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将抽象部分与实现部分分离，使他们都可以独立地变化。&lt;/p&gt;
&lt;p&gt;先来看一个简单的例子，假设我们需要开发一个同时支持PC和手机的坦克游戏，游戏在PC和手机上的功能都一样，有同样的类型，有同样的功能需求变化，而这些游戏中的坦克有多种不同的型号：T50 T60等。根据面向对象的思想，我们可以很容易设计一个坦克(Tank)的抽象类，然后不同的型号都继承抽象类，并且PC和手机上的图形绘制，操作等都是不相同的，所以不同的平台都要提供自己的一套实现：&lt;/p&gt;
&lt;p&gt;坦克抽象类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 坦克的抽象类
/// &amp;lt;/summary&amp;gt;
public abstract class Tank
{
 public abstract void Start();
 public abstract void Attack();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;各种不同的型号&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// T50型号
/// &amp;lt;/summary&amp;gt;
public class T50:Tank
{
 public override void Attack(){}
 public override void Start(){}
}
/// &amp;lt;summary&amp;gt;
/// T60型号
/// &amp;lt;/summary&amp;gt;
public class T60:Tank
{
 public override void Attack(){}
 public override void Start(){}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;手机上的实现&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// MobileT50型号
/// &amp;lt;/summary&amp;gt;
public class MobileT50 : T50
{
 /// &amp;lt;summary&amp;gt;
 /// 启动
 /// &amp;lt;/summary&amp;gt;
 public override void Start(){}
 /// &amp;lt;summary&amp;gt;
 /// 攻击
 /// &amp;lt;/summary&amp;gt;
 public override void Attack(){}
}
/// &amp;lt;summary&amp;gt;
/// MobileT60型号
/// &amp;lt;/summary&amp;gt;
public class MobileT60 : Tank
{
 /// &amp;lt;summary&amp;gt;
 /// 启动
 /// &amp;lt;/summary&amp;gt;
 public override void Start(){}
 /// &amp;lt;summary&amp;gt;
 /// 攻击
 /// &amp;lt;/summary&amp;gt;
 public override void Attack(){}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;PC上的实现&lt;/p&gt;</description></item><item><title>设计模式笔记(7)—适配器模式（结构型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-7-adapter-pattern/</link><pubDate>Thu, 26 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-7-adapter-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将一个类的接口转换成客户所希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，由于应用环境的变化，常常要将“一些现存的对象”放在心的环境中应用，但是新环境要求的接口是这些现存对象所不满足的。&lt;/p&gt;
&lt;p&gt;适配的意思是在不改变原有实现的基础上，将原先不兼容的接口转换为兼容的接口。在我们的生活中有着很多适配器的例子，笔记本的电源适配器、一些卡的USB读卡器等等。&lt;/p&gt;
&lt;p&gt;在Gof23这本书中将适配器模式分成了两种：对象适配器和类适配器&lt;/p&gt;
&lt;p&gt;对象适配器&lt;/p&gt;
&lt;p&gt;&lt;img src="https://img.fwhyy.com/2022/202201281852658.webp" alt="2010-12-29_140647" loading="lazy" decoding="async"&gt;
&lt;/p&gt;
&lt;p&gt;上图中的Target是客户所期待的，希望去使用的类或接口。Adaptee是被适配的对象。Adapter为适配的对象。首先将上图中的结构还原成代码，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
 /// 客户要使用的类
 /// &amp;lt;/summary&amp;gt;
 public abstract class Target
 {
 public abstract void Request();
 }

 /// &amp;lt;summary&amp;gt;
 /// 被适配的类
 /// &amp;lt;/summary&amp;gt;
 public class Adaptee
 {
 public void SpecificRequest()
 { 

 }
 }

 /// &amp;lt;summary&amp;gt;
 /// 适配对象
 /// &amp;lt;/summary&amp;gt;
 public class Adapter : Target
 {
 private Adaptee adapee = new Adaptee();

 public void Request()
 {
 adapee.SpecificRequest();
 }
 }

 /// &amp;lt;summary&amp;gt;
 /// 客户程序
 /// &amp;lt;/summary&amp;gt;
 public class App
 {
 static void Main(string[] args)
 {
 Target target = new Adapter();
 //对客户来说是调用的Request，实际上是调用的SpecificRequest
 target.Request();
 }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;接着根据上面的思路来看一个实际例子，我们要来实现一个对栈的操作，有一个IStact接口，里面有三个方法Push(进栈)、Pop(出栈)和GetTopItem(取最顶层元素)，这个IStact接口将相当于上面的Target，想要实现进栈出栈的操作，如果自己去实现数据结构显得比较麻烦，在此可以将net提供的ArrayList类拿来一用，ArrayList类就是被适配的对象，相当于上面的Adaptee。在写一个适配类StactAdapter类完成功能就可以了。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// 栈的接口
/// &amp;lt;/summary&amp;gt;
public interface IStack
{
 void Push(object item);
 void Pop();
 Object GetTopItem();
}
/// &amp;lt;summary&amp;gt;
/// 对象适配器
/// &amp;lt;/summary&amp;gt;
public class StactAdapter:IStack
{
 ArrayList list;
 /// &amp;lt;summary&amp;gt;
 /// 构造函数中实例化ArrayList
 /// &amp;lt;/summary&amp;gt;
 public StactAdapter()
 {
 list = new ArrayList();
 }
 /// &amp;lt;summary&amp;gt;
 /// 进栈
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;param name=&amp;#34;item&amp;#34;&amp;gt;压入栈的元素&amp;lt;/param&amp;gt;
 public void Push(object item)
 {
 list.Add(item);
 }
 /// &amp;lt;summary&amp;gt;
 /// 出栈
 /// &amp;lt;/summary&amp;gt;
 public void Pop()
 {
 list.RemoveAt(list.Count - 1);
 }
 /// &amp;lt;summary&amp;gt;
 /// 取最顶层的元素
 /// &amp;lt;/summary&amp;gt;
 /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
 public Object GetTopItem()
 {
 return list[list.Count - 1];
 }
}
/// &amp;lt;summary&amp;gt;
/// 客户调用
/// &amp;lt;/summary&amp;gt;
public class App
{
 static void Main(string[] args)
 {
 IStack myStack = new StactAdapter();
 myStack.Push(&amp;#34;oec2003&amp;#34;);
 myStack.Push(&amp;#34;oec2004&amp;#34;);
 myStack.Push(&amp;#34;oec2005&amp;#34;);
 myStack.Pop();
 Console.WriteLine(myStack.GetTopItem());
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Adapter模式理解起来也非常简单，IStact中的Push和Pop方法就是添加元素和移除元素的功能，正好系统类ArrayList中就提供了Add和RemoveAt这样的方法，所以就可以拿来借用，通过适配器类（StactAdapter）的转换使得Push和Pop方法可以支持添加和移除元素的功能，就像我们经常使用的笔记本一样，本来现实中的电压和笔记本所需要的电压不相符，通过电源适配器的转换就将现实中的电压转换成笔记本所需要的电压。&lt;/p&gt;</description></item><item><title>设计模式笔记(6)—原型模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-6-prototype-pattern/</link><pubDate>Tue, 24 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-6-prototype-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;使用原型实例指定创建对象的种类，然后通过拷贝这些原型来创建新的对象。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，经常面临着“某些结构复杂的对象”的创建工作，但由于需求的变化，这些对象将成面临着剧烈的变化，但他们拥有比较稳定一致的接口。&lt;/p&gt;
&lt;p&gt;假设在一些打斗游戏场景中，有这样一些角色，普通(NormalActor),可以飞的(FlyActor)，可以潜水的(WaterActor)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class NormalActor { }
public abstract class FlyActor { }
public abstract class WaterActor { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的三个类都是抽象类，自然会有具体的类来继承这些抽象类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class NormalActorA : NormalActor { }
public class FlyActorA : FlyActor { }
public class WaterActorA : WaterActor { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在游戏运行中就会去使用这些角色的具体类，如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class GameSystem
{
 public void Run()
 {
 NormalActorA normalActor1 = new NormalActorA();
 NormalActorA normalActor2 = new NormalActorA();
 NormalActorA normalActor3 = new NormalActorA();
 NormalActorA normalActor4 = new NormalActorA();
 NormalActorA normalActor5 = new NormalActorA();

 FlyActorA flyActor1 = new FlyActorA();
 FlyActorA flyActor2 = new FlyActorA();

 WaterActorA waterActor1 = new WaterActorA();
 WaterActorA waterActor2 = new WaterActorA();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在GameSystem类中，我们直接使用具体类（NormalActorA）等来创建对象，GameSystem就对这些具体类产生了依赖，在DIP（依赖倒置原则）中讲到抽象不应依赖具体实现，具体实现应依赖于抽象，所以GameSystem中的代码要进行如下改动&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class GameSystem
{
 public void Run(NormalActor normalActor, FlyActor flyActor,
 WaterActor waterActor)
 {
 NormalActor normalActor1 = normalActor.Clone();
 NormalActor normalActor2 = normalActor.Clone();
 NormalActor normalActor3 = normalActor.Clone();
 NormalActor normalActor4 = normalActor.Clone();
 NormalActor normalActor5 = normalActor.Clone();

 FlyActor flyActor1 = flyActor.Clone();
 FlyActor flyActor2 = flyActor.Clone();

 WaterActor waterActor1 = waterActor.Clone();
 WaterActor waterActor2 = waterActor.Clone();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;经过修改在GameSystem类中已经看不到具体类的影子了，创建对象是通过传入的抽象类类型的参数的Clone方法来创建，关于Clone方法在后面讲到，这样GameSystem就只依赖于抽象了。&lt;/p&gt;</description></item><item><title>设计模式笔记(5)—工厂方法模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-5-factory-method-pattern/</link><pubDate>Sun, 22 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-5-factory-method-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;定义一种用于创建对象的借口，让子类决定实例化哪一个类，Factory Method使得一个类的实例化延迟到子类。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，经常面临着“某个对象”的创建工作；由于需求的变化，这个对象经常面临着剧烈的变化，但是它却拥有比较稳定的借口。&lt;/p&gt;
&lt;p&gt;假设有这样的一个场景，有一个汽车类和一个汽车测试框架类，汽车测试框架负责对汽车来进行测试，通常情况下我们会想下面这样写。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Car
{
 public void Startup() { }

 public void Run(){ }

 public void Turn(Direction direction) { }

 public void Stop() { }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;测试框架类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class CarTestFramework
{
 public void BuildTestContext()
 {
 Car car = new Car();
 //do something
 }

 public void DoTest()
 {
 Car car = new Car();
 //do something
 }

 public void GetTestData()
 {
 Car car = new Car();
 //do something
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在上面的测试框架类CarTestFramework中的每个方法都有可能去实例化Car类。上面的代码中是直接实例化的
Car类。这样测试框架类和汽车之间有很强的依赖关系。实际中我们的测试框架类不可能只测试一种类型的汽车，
所以当被测试的车的类型发生变化时，测试框架类中也要变化，这当然不是我们想要的。现在就把汽车类给抽象
起来。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class AbstractCar
{
 public abstract void Startup();

 public abstract void Run();

 public abstract void Turn(Direction direction);

 public abstract void Stop();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;抽象的汽车类创建了，那么测试框架类也会发生相应的变化，我们可能会很快地拿AbstractCar特换掉Car，如下：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;class CarTestFramework
{
 public void BuildTestContext()
 {
 AbstractCar car = new AbstractCar();
 //do something
 }

 //....
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;很容易可以看出来，上面的代码其实是错误的，抽象类不能实例化。这时可能还会想到另外一种方法用抽象类来实例化子类。&lt;/p&gt;</description></item><item><title>设计模式笔记(4)—生成器模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-4-generator-pattern/</link><pubDate>Sat, 21 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-4-generator-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;将一个复杂对象的构建与其表示相分离，使其同样的构建过程可以创建不同的表示。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中，有时侯面临着一个复杂对象的创建工作，这个发展对象通常是由各个部分的子对象用一定的算法构成；由于需求的变化，这个复杂的对象的各个部分经常面临着巨大的变化，但是将他们组合起来的算法相对稳定。&lt;/p&gt;
&lt;p&gt;还是拿游戏中的房屋作为例子来讲，房屋由门、窗户、墙、地板、天花板组成。这些组成部分可能是经常要发生变化的。如果按常规设计，这些组成部分中的任何一个发生变化时都将使房屋重建，生成器模式的作用就是要使这些组件的变化不影响到房屋。首先构建一个House类&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class House
{
 //该类中可能包含复杂的创建逻辑
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面的是一个抽象的构建类，用类构建房屋的组件&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public abstract class Builder
{
 public abstract void BuildDoor();
 public abstract void BuildWall();
 public abstract void BuildWindow();
 public abstract void BuildFloor();
 public abstract void BuildHouseCeiling();

 public abstract House GetHouse();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;假设在一个游戏管理类（GameManager）中来完成对房屋的构建&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class GameManager
{
 public static House CreateHouse(Builder builder)
 {
 builder.BuildDoor();

 builder.BuildWindow();
 builder.BuildWindow();

 builder.BuildWall();
 builder.BuildWall();
 builder.BuildWall();
 builder.BuildWall();

 builder.BuildFloor();
 builder.BuildHouseCeiling();

 return builder.GetHouse();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在GameManager类中都是使用的抽象类来完成房屋的构建，所以GameManager类基本上是稳定的，可能出现变化的是创建门或是窗户的个数，当然这个我们可以在数据库中记录。稳定的部分已经创建，现在就来创建经常会变动的部分，假设现在需要构建一个罗马风格的房屋，可以写一个RomanHouse和一个RomanHouseBuilder类来继承House类和Builder类。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class RomanHouse:House {}

public class RomanHouseBuilder : Builder
{
 public override void BuildDoor() { }
 public override void BuildFloor() {}
 public override void BuildHouseCeiling(){ }
 public override void BuildWall(){}
 public override void BuildWindow(){}
 public override House GetHouse()
 {
 return new RomanHouse();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果需要其他风格的访问，同可以创建相应的类继承House和HouseBuilder就可以。&lt;/p&gt;
&lt;p&gt;客户端调用的代码如下&lt;/p&gt;</description></item><item><title>设计模式笔记(3)—抽象工厂模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-3-abstract-factory-pattern/</link><pubDate>Fri, 20 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-3-abstract-factory-pattern/</guid><description>&lt;h2 id="gof定义"&gt;Gof定义&lt;/h2&gt;
&lt;p&gt;提供一个借口，让该接口负责创建一系列_相关或者相互依赖的对象_，无需指定他们具体的类。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;在软件系统中经常面临着_一系列相互依赖的对象_的创建的工作，同时由于需求的变化，往往存在着更对系列对象的创建。&lt;/p&gt;
&lt;p&gt;常规的对象创建的方法，直接使用new关键字&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Road road = new Road();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这样直接new会有一个问题，不能应对具体实例化类型的变化，比如说有不同的Road类型需要被实例化的时候就需要来更改此处的代码。解决这个问题的办法就是封装变化点，变化点也是相对而言的，比如在项目中有些地方会经常更具客户的需求而作改动，我们就可以将其封装起来。拿上面的那行代码来说，因为可能有不同类型的Road需要被创建，变化点就是“对象的创建”。&lt;/p&gt;
&lt;p&gt;一种比较简单的解决方法，看下面的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class RoadFactory
{
 public static Road CreateRoad()
 {
 return new Road();
 }
}
//调用的代码
public class Test
{
 static void Main(string[] args)
 {
 Road road = RoadFactory.CreateRoad();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在需求有了改变，需要创建一种另一种类型的路HighRoad，只需更改工厂类的代码就可以，调用的地方不用做修改，如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class RoadFactory
{
 public static Road CreateRoad()
 {
 return new HighRoad();
 }
} 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在需求又有了改变，比如在游戏的开发场景中，我们需要构建道路、房屋、丛林等等对象，按照上面的思路我 可以写成下面这样的代码&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//客户程序
 public class Test
 {
 static void Main(string[] args)
 {
 Road road = GameObjectFactory.CreateRoad();
 Building building = GameObjectFactory.CreateBuilding();
 Jungle jungle = GameObjectFactory.CreateJungle();
 }
 }

 public class GameObjectFactory
 {
 public static Road CreateRoad()
 {
 return new Road();
 }
 public static Building CreateBuilding()
 {
 return new Building();
 }
 public static Jungle CreateJungle()
 {
 return new Jungle();
 }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;以上的代码属于一种简单工厂的实现，将对象的创建放到一个单独的工厂类中，实现了和客户程序的分离，不过 不能应对不同系列对象的变化，比如有不同风格的游戏场景，对于要实现不同风格场景中的道路、房屋等对象的 创建，上面的代码就难以实现。对于有_不同系列对象_这样的需求，变化点转移到了工厂类的内部，上面的代码中 对象的创建是在工厂类中的静态方法中写死的，不能应对变化，如果我们另外创建一个能适应其他系列的工厂类， 那么客户程序就会发生改变，这不是我们希望看到的。要解决此类问题必须使用面向对象的技术来封装变化点。
结构图&lt;/p&gt;</description></item><item><title>设计模式笔记(2)—单件模式（创建型）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-2-singleton-pattern/</link><pubDate>Thu, 19 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-2-singleton-pattern/</guid><description>&lt;h2 id="gof-定义"&gt;Gof 定义&lt;/h2&gt;
&lt;p&gt;保证一个类仅有一个实例，并提供一个该实例的全局访问点。&lt;/p&gt;
&lt;h2 id="动机"&gt;动机&lt;/h2&gt;
&lt;p&gt;保证在系统中只存在一个实例，这样才能保证逻辑的正确性和良好的效率。&lt;/p&gt;
&lt;h2 id="单件模式单线程环境下实现"&gt;单件模式单线程环境下实现&lt;/h2&gt;
&lt;p&gt;看下面一段代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Singleton
{
 private static Singleton _instance;
 //定义为私有，让类的使用者不能直接new一个该类的实例
 private Singleton() { }
 public static Singleton Instance
 {
 get
 {
 if (_instance == null)
 {
 _instance = new Singleton();
 }
 return _instance;
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码中将Singleton类的构造函数设置为私有，如果试图去用new去创建一个Singleton的实例，会出现编译错误&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Test
{
 public static void Main()
 {
 //Singleton不可访问，因为他受保护级别限制
 Singleton t = new Singleton();
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;要创建Singleton的实例我们可以像下面这样做&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Test
{
 public static void Main()
 {
 Singleton t = Singleton.Instance;
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;上面的代码完成了一个最简单的单例模式的实现，保证了实例的唯一性，如下的测试代码是可以顺利通过的&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[TestMethod()]
public void Test()
{
 Singleton t1 = Singleton.Instance;
 Singleton t2 = Singleton.Instance;

 Assert.AreEqual(true, t1.Equals(t2));
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="单件模式多线程环境下实现"&gt;单件模式多线程环境下实现&lt;/h2&gt;
&lt;p&gt;在多线程环境下上面代码仍然有可能得到Singleton类的多个对象实例，为什么在多线程环境下会可能创建出多个实例呢？看下面代码：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public class Singleton
{
 private static Singleton _instance;
 //定义为私有，让类的使用者不能直接new一个该类的实例
 private Singleton() { }
 public static Singleton Instance
 {
 get
 {
 //线程A执行到此进行if判断，会进入到if语句里面
 //在线程A执行_instance = new Singleton(); 前，线程B也到了if判断处，
 //此时_instance还没有被创建出来仍然为null，线程B也会进入到if语句中
 //这样线程A和线程B会各自构建一个Singleton的实例
 if (_instance == null)
 {
 _instance = new Singleton();
 }
 return _instance;
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;所以上面的代码示例只能应用在单线程的环境下，如果需要实现在多线程环境下的单件模式就需要对上面的代码进行改进，如下&lt;/p&gt;</description></item><item><title>设计模式笔记(1)—开篇（文章索引）</title><link>https://fwhyy.com/2009/11/design-patterns-notes-1-index/</link><pubDate>Wed, 18 Nov 2009 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2009/11/design-patterns-notes-1-index/</guid><description>&lt;h2 id="概念"&gt;概念&lt;/h2&gt;
&lt;p&gt;设计模式描述了软件设计过程中某一类常见问题的一般性的解决方案。&lt;/p&gt;
&lt;p&gt;面向对象的设计模式描述了面向对象设计过程中，在特定场景下类与相互通讯的对象之间常见的组织关系。&lt;/p&gt;
&lt;h2 id="设计模式与面向对象"&gt;设计模式与面向对象&lt;/h2&gt;
&lt;p&gt;面向对象设计模式解决的是“类与相互通信的对象之间的组织关系。包括他们的角色、职责、协作方式几个方面。&lt;/p&gt;
&lt;p&gt;面向对象设计模式是“好的面向对象设计”，所谓“好的面向对象设计”是那些可以满足“因对变化，提高复用的设计”。&lt;/p&gt;
&lt;p&gt;面向对象设计模式描述的是软件设计，因此他是独立于编程语言的，但是面向对象设计模式的最终实现仍然要使用面向对象编程语言来表达。&lt;/p&gt;
&lt;p&gt;面向对象设计模式不像算法技巧，可以照搬照用，他是建立在对“面象对象”纯熟、深入的理解的基础上的经验性认识。&lt;/p&gt;
&lt;h2 id="从设计原则到设计模式"&gt;从设计原则到设计模式&lt;/h2&gt;
&lt;p&gt;针对接口编程，而不是针对实现编程—客户无需知道所有使用对象的特定类型，只需要知道对象拥有客户所期望的接口。&lt;/p&gt;
&lt;p&gt;优先使用对象组合，而不是类继承—类继承通常为“白箱复用”，对象组合通常为“黑箱复用”。继承在某种程度上破坏了封装性，子类父类耦合度高；而面向组合只要求组合的对象具有良好定义的接口，耦合度低。&lt;/p&gt;
&lt;p&gt;封装变化点—使用封装来创建对象之间分界曾，让设计者可以在分界曾的一侧进行修改，而不会对另一侧产生不良的影响，从而实现层次间的松耦合。&lt;/p&gt;
&lt;p&gt;使用重构得到模式—设计模式的应用不宜先入为主，一上来就是用设计模式是对设计模式的最大无用。没有一步到位的设计模式。&lt;/p&gt;
&lt;h2 id="几个设计原则"&gt;几个设计原则&lt;/h2&gt;
&lt;p&gt;在设计模式的使用中无时无刻都在贯穿着下面这几个原则，所以说理解了这几个设计原则对学习和理解设计模式有很大的帮助。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ol&gt;
&lt;li&gt;单一职责原（SRP）：一个类应该仅有一个引起它变化的原因。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="2"&gt;
&lt;li&gt;开放封闭原则（OCP）：类模块应该是可以扩展的，但是不可以修改（多扩展开放，对修改封闭）&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Liskov替换原则（LSP）：子类必须能够替换他们的基类&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="4"&gt;
&lt;li&gt;依赖倒置原则（DIP）：高层模块不应该依赖于底层模块，二者都应该依赖于抽象；抽象不应该依赖于实现细节，实现细节应该依赖于抽象。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ol start="5"&gt;
&lt;li&gt;接口隔离原则（ISP）：不应该强迫客户程序依赖于他们不用的方法。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面只是简单给出了定义，网上有很多关于这些原则的详细介绍。&lt;/p&gt;
&lt;p&gt;下面简单谈一下我自己对设计模式的认识，设计模式很早就接触了，不过实际在项目中使用过的也只是很少的几个，现在市面上有很多关于设计模式的书，其中不乏有些很生动的例子，非常容易理解，但设计模式并不是写些简单的Demo，个人感觉从很熟悉那些简单的Demo到能够灵活在项目中运用这中间有很长的路要走，需要我们多写、多思考，多总结。之所以要使用设计模式，是因为当变化来临时我们能更方便快捷地解决问题，并且有利于以后的维护。如果没有需求的变化，完全可以用自己认为最简单直接的方式去实现功能，不过需求往往是多变的。我们通常所讲的设计模式指的是面向对象设计模式，所以学习好面向对象的知识是学习面向对象设计模式的前提。最近又将几年前的关于设计模式的webcast讲座翻出来听了听，感觉收获颇多，也顺便做了些笔记以备后用。&lt;/p&gt;
&lt;h2 id="设计模式的分类"&gt;设计模式的分类&lt;/h2&gt;
&lt;p&gt;设计模式分类创建型、结构型、行为型三类。&lt;/p&gt;
&lt;h3 id="创建型"&gt;创建型&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-2-singleton-pattern/"&gt;Singleton 单件&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-3-abstract-factory-pattern/"&gt;Abstract Factory 抽象工厂模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-4-generator-pattern/"&gt;Builder 生成器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-5-factory-method-pattern/"&gt;Factory Method 工厂方法模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-6-prototype-pattern/"&gt;Prototype 原型模式&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="结构性"&gt;结构性&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/11/design-patterns-notes-7-adapter-pattern/"&gt;Adapter 适配器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-8-bridge-pattern/"&gt;Bridge 桥接模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-9-portfolio-pattern/"&gt;Composite 组合模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-10-decorative-pattern/"&gt;Decorator 装饰模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-11-appearance-pattern/"&gt;Facade 外观模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-12-flyweight-pattern/"&gt;Flyweight 享元模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-13-proxy-pattern/"&gt;Proxy 代理模式&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="行为型"&gt;行为型&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-14-template-method-pattern/"&gt;TemplateMethod 模板方法模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2009/12/design-patterns-notes-15-command-pattern/"&gt;Command 命令模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-16-interpreter-pattern/"&gt;Interpreter 解释器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-17-mediator-pattern/"&gt;Mediator 中介者模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-18-iterator-pattern/"&gt;Iterator 迭代器模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-19-observer-pattern/"&gt;Observer 观察者模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-20-chain-of-responsibility-pattern/"&gt;Chain Of Responsibility 职责链模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-21-memo-pattern/"&gt;Memento 备忘录模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-22-state-pattern/"&gt;State 状态模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/01/design-patterns-notes-23-strategy-pattern/"&gt;Strategy 策略模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/02/design-patterns-notes-24-visitor-pattern/"&gt;Visitor 访问者模式&lt;/a&gt;
&lt;a href="http://blog.fwhyy.com/2010/02/design-patterns-notes-25-summary/"&gt;总结&lt;/a&gt;&lt;/p&gt;</description></item><item><title>对设计模式的一点理解</title><link>https://fwhyy.com/2007/09/a-little-understanding-of-design-patterns/</link><pubDate>Sat, 08 Sep 2007 00:00:00 +0800</pubDate><guid>https://fwhyy.com/2007/09/a-little-understanding-of-design-patterns/</guid><description>&lt;p&gt;说起设计模式，不得不提的是GoF23种设计模式，这些设计模式是在历史性的一本经典著作《设计模式：可复用面向对象软件的基础》被描述的，这本书的四位作者并称为Gang of Four(GoF) 。由于这本书极具影响力，所以我们通常所说的设计模式就隐含地表示为“面向对象设计模式”，但这并不意味着“设计模式”就等同于“面向对象设计模式”。&lt;/p&gt;</description></item></channel></rss>