23个设计模式笔记
程序员文章站
2022-03-03 09:50:29
参考:http://dofactory.com/Patterns/Patterns.aspx 参考:http://www.quickiwiki.com/en/Design_pattern_%28computer_science%29#Classification_and_list Design Pa ......
参考:http://dofactory.com/Patterns/Patterns.aspx
参考:http://www.quickiwiki.com/en/Design_pattern_%28computer_science%29#Classification_and_list
Design Pattern:为解决那些反复出现的问题,比如
Getting a notification when a process completes, or a state chanes
Making a complex API easier to work with
Adding functionality to an existing object
Behaving in distinct ways based on a current mode or state.
Looping through elements of a collection or sequence
Observer模式 (订阅者与观察者):属于“behavioral pattern" 行为模式
定义:Define a one-to-many dependency between objects so that when one object changese state, all its dependents are notified and updated automatically.
需要预见的pub/sub结果:
1. Notification may never come, 不能指望它,通知是unreliable的
2. Notification may come repeatly 注意处理duplication
3. Notification may come quickly, 所以要早点准备去接受status change
4. Strong references may stop the GC disposing objects
需要的一些方法
Observer<T> 即监听者/订阅者/subcriber -> onNext(T value), onCompleted(), onError(Exception ex),
Observable<T> 即publisher/可被监听者 -> IDisposable Subscribe (IObserver<T> observer)
比如Prism中的 观察者/监听器模式,如果看到subscribe, observe, listener,那就都是这种模式,还有异步callback也是。比如, iOS中的NotificationCenter。一般实现的时候,往往会结合装饰者模式、职责链模式或者模板方法模式给监听器添加额外的灵活性和功能。
这种模式,单一职责,解耦,了解到pub/sub中如何各施其责,以及互通,负责对象销毁时的事件调用等,很重要。
扩展:在PluralSight的《Design Pattern On-ramp》中用到了WPF Prism的pub/sub,可以查看 http://msdn.microsoft.com/en-us/library/ff921122.aspx 其中提到ComplexEventAggregator, SubscriptionFilter, 防止Publisher被dispose时的GC所增加的strong/weak reference设置 (keepSubscriberReferenceAlive),还有一个ThreadOption.BackgroundThread/PublisherThread, UIThread选项
pub/sub wiki: http://www.quickiwiki.com/en/Publish/subscribe
Proxy模式(代理模式):属于“structural pattern" 结构模式
GoF描述:Provide a surogate or placeholder for another object to control access to it.
日常:企业许可或授于(多个)猎头公司代理其企业寻找企业需要的人才。
.NET: SOAP service proxy
意义:(摘自:http://www.cnblogs.com/kid-li/archive/2006/10/18/532192.html )
“增加一层间接层”是软件系统中对许多负责问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。"The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate." (from http://www.quickiwiki.com/en/Proxy_pattern)
在我们日常的工作中也常常用到代理模式,比如对于三层结构或者N- tiers结构中DAL数据访问层,它把对数据库的访问进行封装。BLL业务层的开发者只是调用DAL中的方法来获得数据。
再比如前一段时间看了看AOP和Remoting方面的资料,对于跨越应用程序域的访问,要为客户应用程序提供一个TransparentProxy(透明代理),客户程序实际上是通过访问这个代理来访问实际的类型对象。
常用到的Service Reference中的xxClient()也是最常用的代理模式,将client与service分隔。 具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象作细粒度的控制,有些可能对组件模块提供抽象代理层,在架构层次对对象作proxy。 proxy并不一定要求保持接口的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。例如上面的那个例子,代理类型ProxyClass和被代理类型LongDistanceClass可以不用继承自同一个接口,正像GoF《设计模式》中说的:为其他对象提供一种代理以控制这个对象的访问。代理类型从某种角度上讲也可以起到控制被代理类型的访问的作用。 Consequences: 1. A remote proxy can hide the fact that an object resides in a different process or across a network. 2. The proxy must be kept synchronized with the real object. 扩展:jdon中这篇文章 http://www.jdon.com/designpatterns/designpattern_proxy.htm 给出了一些扩展,如 “动态代理与AOP” 授权机制:不同级别的用户对同一对象拥有不同的访问权利(比如企业分发给不同猎头不同职位,不同授权) 缓存机制:某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动,比如thumbnail/placeholder,能操作到代理,代理再去提取真实图片,即“如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.” 代理模式在业务建模和技术架构上有不同应用,技术架构上有:访问代理(Access Proxy)、虚拟代理和远程代理等。 动态代理:只需要一个代理类,就可以为所有原始类实现代理功能。 Iterator模式(迭代模式):属于“hebavioural pattern“行为模式 GoF描述:provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. 日常:遥控,上一个频道,下一个频道 .NET:集合, 迭代器,迭代器对象 Iterator Consequences: 1. Adding or removing items from an aggregate during iteration can invalidate the Iterator 2. Mutliple Iterators can act on a single aggregate object. .NET中的迭代:IEnumberator, .GetEnumerabor(), .MoveNext()返回是否有next,并将值或指针给到.Current() IEnumberable<T>,实现了迭代的接口,如HybridCollection, HashTable, Stack, ObservableCollection,
IEnumberator<T> -> T Current, bool MoveNext(), void Reset(), void Dispose(). enumerable.GetEnumberator(),是指针,参看clr via c#的#16 数组 Practice: 建一个实现IEnumrable<T>的类(承载顺序队列的类),建一个实现IEnumberator<T>的类(承载当前element对象值或指针的类)。前者要实现T GetEnumerator(),后者要实现T Current, bool MoveNext(), void Reset(), void Dispose() foreach是针对实现了enumerable/enumerator的类 使用yield return来迭代 (c# 2.0), 即,不在后者(enumerator)中去实现return current element value, 而在前者(enumerable)中的GetEnumerator方法中通过直接操作循环/loop thru elements, 并yield return返回到其enumerator。详细清楚的资料参看 http://blog.csdn.net/chengly0129/article/details/7874222 ,在所有返回值为IEnumerator<T>, IEnumerable<T>的方法中都可以使用yield return来“压”值进迭代对象的[index]。另:在 yield break 语句中,控制权将无条件地返回给迭代器的调用方,该调用方为枚举器对象的 IEnumerator<T>.MoveNext 方法 或 Dispose 方法。
public IEnumerator<int> GetEnumerator()//注意方法名 {yield return 0; yield return 1;yield return 2;yield return 3;} 这一段是指将0压进[0], 1压进[1]..等 疑问:何时需要将logic包装进一个迭代对象中? Chaine of Responsbilities模式(职责链模式/CoR Pattern):属于行为模式 GoF描述: avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chine the receiving objects and pass the request along the chaine until an object handles it. 日常:客服L1->L2->L3 .NET:异常处理bubble-up,Workflow CoR consequences: if none of the receivers handle the message, then the message wil fall off the end of the chain. Approval Engine:每个级别定义rule,各个rule串联起来,每个rule的关注点只有两个,上一层,和下一层,且不重要,所以可以串联起来,且每个rule/node不用关注整个high-level(让我看起《失控》里的机器人一章) Facade模式(外观模式):结构模式 GoF: provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 日常:统一遥控器,有的发烧友就这样,把所有的电器都放进一个unified remote controller去操作,一键就开电视,另一个键开收音机等。 .NET:foreach就是,它“隐藏”了创建/提取enumerator的功能,借助foreach (var item in list)的item,就可以使用到迭代器功能。 1、从客户程序的角度看,Facade模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Facade接口的变化。
2、Facade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。Facade很多时候更是一种架构设计模式。 将复杂的背后的流程隐藏起来,给用户一个简单易用的方法,比如UI Thread v.s. Background Thread Facade consequences: 1. If we want to expose more functtionality from the subsystem, we may need to update, or create a new facade. 2. Since the facade hides complexity, the entire API is often not available. Factory Method Pattern (工厂模式):creational pattern GoF: define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化那个类。FactoryMethod使得一个类的实例化延迟到子类。 .NET实例:IHttpHandlerFactory 仓库工厂模式(Repository Factory Pattern)- 访问代码重复,仓库相当于具体工厂中的实体 简单工厂模式 抽象工厂Abstract Factory模式:creational pattern 提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。 Abstract Factory模式与Factory模式的区别是:Factory模式有一个抽象产品类,Abstract Factory模式有多个;Factory模式的具体工厂类创建一个具体产品,而Abstract Factory模式的具体工厂类可以创建多个。Abstract Factory模式相对于Factory模式,最大的优点是易于切换产品系列。比如,对于下面的代码示例,如果想从罗技设备切换为微软设备,只需要修改具体工厂为MicrosoftDevicesFactory,如果DevicesFactory生产很多种设备,方便显而易见。factory method针对的是一个产品等级结构,abstract factory面向多个产品等级结构。 Decorator模式(装饰模式)结构类模式: 不需要改变类本身,基于它之上,再建一个wrapper去扩展它(可以使用同一个基类),比如在一个类上面包一层cache Adaptor模式(适配器模式):结构类模式 GoF: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。 Gof《设计模式》中提到了两种Adapter适配器模式,一种叫对象适配器模式,另一种叫类适配器模式。对象适配器模式的结构如上图,也就是我刚才举的那个例子,那什么是类适配器模式呢?实际上类适配器模式就是让Adapter的实现继承Adaptee。换句话说:类适配器模式是以继承的方式来实现,而对象适配器模式是以组合的方式实现。以前我们说过:继承增加了模块间的耦合程度,而组合降低了耦合程度,所以有人建议多使用对象适配器模式,少用类适配器模式。 Builder模式(构建者模式):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。一步步创建复杂的对象,它允许用户只通过制定复杂对象的类型和内容就可以创建它们,用户不知道内部的具体构建细节。 身边: .NET: StringBuilder Stategy模式(策略模式):策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。 设计原则: 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。这个概念很简单,几乎是每个设计模式背后的精神所在,所有的模式都提供了一套方法让系统中的某部分改变不会影响其它部分。分开变化和不变化的部分。 针对接口编程,而不是针对实现编程。 多用组合,少用继承。使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以在运行时动态地改变行为。 Bridge模式(桥接模式):Decouple an abstraction from its implementation so that the two can vary independently. 将抽象与实现分离,以使得二者可以独立变化。(即“loosely coupled") Composite模式(组合模式):Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 Flyweight模式(享元模式):Use sharing to support large numbers of fine-grained objects efficiently. Singleton模式(单例模式):Ensure a class has only one instance and provide a global point of access to it. Command模式(命令模式): Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. Interpreter模式(翻译模式):Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. .NET: regex Mediator模式: Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. Memento (recognizeable by behavioral methods which internally changes the state of the whole instance): 如Serializable Template Method模式(模板模式):定义一个操作中的算法的骨架,而将一些步骤延迟到子类忠。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 GOF设计模式与身边的.NET:
Builder Pattern:StringBuilder
Factory Method:IHttpHandlerFactory
Adapter Pattern:COM Interop、DataAdapter
Decorator Pattern:BufferedStream、CryptoStream
Composite Pattern:Enterprise Library2.0中的ObjectBuilder
Facade Pattern:Duwamish
Flyweight Pattern:.NET中的String类型
Template Method:服务器控件
Command Pattern:MVC
Iterator Pattern:IEnumerator
Oberver Pattern:委托和事件
Strategy Patterm:System.Configuration.Provider、IComparer
Singleton Pattern:Remoting的Singleton
在我们日常的工作中也常常用到代理模式,比如对于三层结构或者N- tiers结构中DAL数据访问层,它把对数据库的访问进行封装。BLL业务层的开发者只是调用DAL中的方法来获得数据。
再比如前一段时间看了看AOP和Remoting方面的资料,对于跨越应用程序域的访问,要为客户应用程序提供一个TransparentProxy(透明代理),客户程序实际上是通过访问这个代理来访问实际的类型对象。
常用到的Service Reference中的xxClient()也是最常用的代理模式,将client与service分隔。 具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象作细粒度的控制,有些可能对组件模块提供抽象代理层,在架构层次对对象作proxy。 proxy并不一定要求保持接口的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。例如上面的那个例子,代理类型ProxyClass和被代理类型LongDistanceClass可以不用继承自同一个接口,正像GoF《设计模式》中说的:为其他对象提供一种代理以控制这个对象的访问。代理类型从某种角度上讲也可以起到控制被代理类型的访问的作用。 Consequences: 1. A remote proxy can hide the fact that an object resides in a different process or across a network. 2. The proxy must be kept synchronized with the real object. 扩展:jdon中这篇文章 http://www.jdon.com/designpatterns/designpattern_proxy.htm 给出了一些扩展,如 “动态代理与AOP” 授权机制:不同级别的用户对同一对象拥有不同的访问权利(比如企业分发给不同猎头不同职位,不同授权) 缓存机制:某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动,比如thumbnail/placeholder,能操作到代理,代理再去提取真实图片,即“如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.” 代理模式在业务建模和技术架构上有不同应用,技术架构上有:访问代理(Access Proxy)、虚拟代理和远程代理等。 动态代理:只需要一个代理类,就可以为所有原始类实现代理功能。 Iterator模式(迭代模式):属于“hebavioural pattern“行为模式 GoF描述:provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. 日常:遥控,上一个频道,下一个频道 .NET:集合, 迭代器,迭代器对象 Iterator Consequences: 1. Adding or removing items from an aggregate during iteration can invalidate the Iterator 2. Mutliple Iterators can act on a single aggregate object. .NET中的迭代:IEnumberator, .GetEnumerabor(), .MoveNext()返回是否有next,并将值或指针给到.Current() IEnumberable<T>,实现了迭代的接口,如HybridCollection, HashTable, Stack, ObservableCollection,
IEnumberator<T> -> T Current, bool MoveNext(), void Reset(), void Dispose(). enumerable.GetEnumberator(),是指针,参看clr via c#的#16 数组 Practice: 建一个实现IEnumrable<T>的类(承载顺序队列的类),建一个实现IEnumberator<T>的类(承载当前element对象值或指针的类)。前者要实现T GetEnumerator(),后者要实现T Current, bool MoveNext(), void Reset(), void Dispose() foreach是针对实现了enumerable/enumerator的类 使用yield return来迭代 (c# 2.0), 即,不在后者(enumerator)中去实现return current element value, 而在前者(enumerable)中的GetEnumerator方法中通过直接操作循环/loop thru elements, 并yield return返回到其enumerator。详细清楚的资料参看 http://blog.csdn.net/chengly0129/article/details/7874222 ,在所有返回值为IEnumerator<T>, IEnumerable<T>的方法中都可以使用yield return来“压”值进迭代对象的[index]。另:在 yield break 语句中,控制权将无条件地返回给迭代器的调用方,该调用方为枚举器对象的 IEnumerator<T>.MoveNext 方法 或 Dispose 方法。
public IEnumerator<int> GetEnumerator()//注意方法名 {yield return 0; yield return 1;yield return 2;yield return 3;} 这一段是指将0压进[0], 1压进[1]..等 疑问:何时需要将logic包装进一个迭代对象中? Chaine of Responsbilities模式(职责链模式/CoR Pattern):属于行为模式 GoF描述: avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chine the receiving objects and pass the request along the chaine until an object handles it. 日常:客服L1->L2->L3 .NET:异常处理bubble-up,Workflow CoR consequences: if none of the receivers handle the message, then the message wil fall off the end of the chain. Approval Engine:每个级别定义rule,各个rule串联起来,每个rule的关注点只有两个,上一层,和下一层,且不重要,所以可以串联起来,且每个rule/node不用关注整个high-level(让我看起《失控》里的机器人一章) Facade模式(外观模式):结构模式 GoF: provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 日常:统一遥控器,有的发烧友就这样,把所有的电器都放进一个unified remote controller去操作,一键就开电视,另一个键开收音机等。 .NET:foreach就是,它“隐藏”了创建/提取enumerator的功能,借助foreach (var item in list)的item,就可以使用到迭代器功能。 1、从客户程序的角度看,Facade模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Facade接口的变化。
2、Facade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。Facade很多时候更是一种架构设计模式。 将复杂的背后的流程隐藏起来,给用户一个简单易用的方法,比如UI Thread v.s. Background Thread Facade consequences: 1. If we want to expose more functtionality from the subsystem, we may need to update, or create a new facade. 2. Since the facade hides complexity, the entire API is often not available. Factory Method Pattern (工厂模式):creational pattern GoF: define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化那个类。FactoryMethod使得一个类的实例化延迟到子类。 .NET实例:IHttpHandlerFactory 仓库工厂模式(Repository Factory Pattern)- 访问代码重复,仓库相当于具体工厂中的实体 简单工厂模式 抽象工厂Abstract Factory模式:creational pattern 提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。 Abstract Factory模式与Factory模式的区别是:Factory模式有一个抽象产品类,Abstract Factory模式有多个;Factory模式的具体工厂类创建一个具体产品,而Abstract Factory模式的具体工厂类可以创建多个。Abstract Factory模式相对于Factory模式,最大的优点是易于切换产品系列。比如,对于下面的代码示例,如果想从罗技设备切换为微软设备,只需要修改具体工厂为MicrosoftDevicesFactory,如果DevicesFactory生产很多种设备,方便显而易见。factory method针对的是一个产品等级结构,abstract factory面向多个产品等级结构。 Decorator模式(装饰模式)结构类模式: 不需要改变类本身,基于它之上,再建一个wrapper去扩展它(可以使用同一个基类),比如在一个类上面包一层cache Adaptor模式(适配器模式):结构类模式 GoF: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。 Gof《设计模式》中提到了两种Adapter适配器模式,一种叫对象适配器模式,另一种叫类适配器模式。对象适配器模式的结构如上图,也就是我刚才举的那个例子,那什么是类适配器模式呢?实际上类适配器模式就是让Adapter的实现继承Adaptee。换句话说:类适配器模式是以继承的方式来实现,而对象适配器模式是以组合的方式实现。以前我们说过:继承增加了模块间的耦合程度,而组合降低了耦合程度,所以有人建议多使用对象适配器模式,少用类适配器模式。 Builder模式(构建者模式):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。一步步创建复杂的对象,它允许用户只通过制定复杂对象的类型和内容就可以创建它们,用户不知道内部的具体构建细节。 身边: .NET: StringBuilder Stategy模式(策略模式):策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。 设计原则: 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。这个概念很简单,几乎是每个设计模式背后的精神所在,所有的模式都提供了一套方法让系统中的某部分改变不会影响其它部分。分开变化和不变化的部分。 针对接口编程,而不是针对实现编程。 多用组合,少用继承。使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以在运行时动态地改变行为。 Bridge模式(桥接模式):Decouple an abstraction from its implementation so that the two can vary independently. 将抽象与实现分离,以使得二者可以独立变化。(即“loosely coupled") Composite模式(组合模式):Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 Flyweight模式(享元模式):Use sharing to support large numbers of fine-grained objects efficiently. Singleton模式(单例模式):Ensure a class has only one instance and provide a global point of access to it. Command模式(命令模式): Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. Interpreter模式(翻译模式):Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. .NET: regex Mediator模式: Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. Memento (recognizeable by behavioral methods which internally changes the state of the whole instance): 如Serializable Template Method模式(模板模式):定义一个操作中的算法的骨架,而将一些步骤延迟到子类忠。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 GOF设计模式与身边的.NET:
Builder Pattern:StringBuilder
Factory Method:IHttpHandlerFactory
Adapter Pattern:COM Interop、DataAdapter
Decorator Pattern:BufferedStream、CryptoStream
Composite Pattern:Enterprise Library2.0中的ObjectBuilder
Facade Pattern:Duwamish
Flyweight Pattern:.NET中的String类型
Template Method:服务器控件
Command Pattern:MVC
Iterator Pattern:IEnumerator
Oberver Pattern:委托和事件
Strategy Patterm:System.Configuration.Provider、IComparer
Singleton Pattern:Remoting的Singleton
上一篇: 设计模式 - 策略模式