开发者

What design patterns are used throughout the .NET Framework?

开发者 https://www.devze.com 2023-01-07 01:08 出处:网络
What classes in the .NET Framework 开发者_运维问答implement the various design patterns such as decorator, factory, etc.?Well, what your asking for is probably a VERY extensive list, as design pattern

What classes in the .NET Framework 开发者_运维问答implement the various design patterns such as decorator, factory, etc.?


Well, what your asking for is probably a VERY extensive list, as design patterns are use all over the .NET platform. Here are some examples I can think of off the top of my head:

Adapter

The adapter pattern, a common mechanism of bridging systems and platforms, is implemented in a variety of ways in the .NET framework. One of the most prevalent examples of this in .NET are Runtime Callable Wrappers, or RCW's. RCW's, generated with the tlbimp.exe program, provide adapters that let .NET managed code easily call into legacy COM code via a .NET API.

Factory Method

The factory method pattern is probably one of the most well-known patterns. It is implemented quite commonly throughout the .NET framework, particularly on primitive times, but also on many others. An excellent example of this pattern in the framework is the Convert class, which provides a host of methods to create common primitives from other common primitives.

Additionally, another pervasive form of this pattern are the .Parse() and .TryParse() methods found on many primitive and basic types.

Iterator

The Iterator pattern is implemented via a couple interfaces and some language constructs, like foreach and the yeild keyword in C#. The IEnumerable interface and its generic counterpart are implemented by dozens of collections in the .NET framework, allowing easy, dynamic iteration of a very wide variety of data sets:

IEnumerable<T>
IEnumerator<T>

foreach(var thing in someEnumerable)
{
   //
}

The yeild keyword in C# allows the true form of an iterator to be realized, only incurring the cost of processing an iteration through a loop when that iteration is demanded:

IEnumerable<string> TokenizeMe(string complexString)
{
    string[] tokens = complexString.Split(' ');
    foreach (string token in toekens)
    {
        yield return token;
    }
}

Builder

The Builder pattern is implemented a few times in the .NET framework. A couple of note are the connection string builders. Connection strings can be a picky thing, and constructing them dynamically at runtime can sometimes be a pain. Connection String Builder classes demonstrate the builder pattern ideally:

string connectionString = new SqlConnectionStringBuilder
{
    DataSource = "localhost",
    InitialCatalog = "MyDatabase",
    IntegratedSecurity = true,
    Pooling = false
}.ConnectionString;

Other classes throughout the .NET framework, such as UriBuilder, also implement the builder pattern.

Observer

The observer pattern is a common pattern that allows one class to watch events of another. As of .NET 4, this pattern is supported in two ways: via language-integrated events (tightly coupled observers), and via the IObservable/IObserver interfaces (loosely coupled events).

Classic language events make use of delegates, or strongly-typed function pointers, to track event callbacks in event properties. An event, when triggered, will execute each of the tracked callbacks in sequence. Events like this are used pervasively throughout the .NET framework.

public class EventProvider
{
    public event EventHandler SomeEvent;

    protected virtual void OnSomeEvent(EventArgs args)
    {
        if (SomeEvent != null)
        {
            SomeEvent(this, args); // Trigger event
        }
    }
}

public class EventConsumer
{
    public EventConsumer(EventProvider provider)
    {
        provider.SomeEvent += someEventHandler; // Register as observer of event
    }

    private void someEventHandler(EventArgs args)
    {
        // handle event
    }
}

New with the .NET 4 framework are loosely coupled events. These are accomplished by implementing the IObservable<out T> and IObserver<in T> interfaces, which more directly support the original Observer design pattern. While not directly implemented by any .NET framework types that I am aware of, the core infrastructure for the pattern is an integral part of .NET 4.

public class SomethingObservable: IObservable<SomethingObservable>
{
    private readonly List<IObserver<SomethingObservable>> m_observers;

    public IDisposable Subscribe(IObserver<SomethingObservable> observer)
    {
        if (!m_observers.Contains(observer))
        {
            m_observers.Add(observer);
        }
        var unsubscriber = new Unsubscriber(m_observers, observer)
        return unsubscriber;        
    }

    private class Unsubscriber: IDisposable
    {
        public Unsubscriber(IList<IObserver<SomethingObservable>> observers, IObserver<SomethingObservable> observer)
        {
            m_observers = observers;
            m_observer = observer;
        }

        private readonly IList<IObserver<SomethingObservable>>  m_observers;
        private readonly IObserver<SomethingObservable> m_observer;

        public void Dispose()
        {
            if (m_observer == null) return;
            if (m_observers.Contains(m_observer))
            {
                m_observers.Remove(m_observer);
            }
        }
    }
}

Decorator

The decorator pattern is a way of providing alternative representations, or forms, of behavior through a single base type. Quite often, a common set of functionality is required, but the actual implementation of that functionality needs to change. An excellent example of this in the .NET framework is the Stream class and its derivatives. All streams in .NET provide the same basic functionality, however each stream functions differently.

  • Stream
    • MemoryStream
    • BufferedStream
    • FileStream
      • IsolatedStorageFileStream
    • PipeStream
      • AnonymousPipeClientStream
      • AnonymousPipeServerStream
      • NamedPipeClientStream
      • NamedPipeServerStream
    • CryptoStream
    • GZipStream

Many, many other design patterns are used within the .NET framework. Almost every aspect of .NET, from language to framework to fundamental runtime concepts, are based on common design patterns. Significant portions of the .NET framework, such as ASP.NET, are in and of themselves patterns. Take, for example, the ASP.NET MVC framework, which is an implementation of the web variant of MVC, or Model-View-Controller. The WPF and Silverlight UI frameworks directly support a pattern called MVVM, or Model-View-ViewModel. The ASP.NET pipeline itself is a collection of patterns, including intercepting filter, page controller, router, etc. Finally, one of the most commonly used patterns, composition, is used so extensively in the .NET framework that it is probably one of the most fundamental patterns of the entire framework.


Off the top of my head :

  • The Abstract Factory pattern is used in the ADO.NET 2.0 infrastructure (DbProviderFactory class)
  • The Template Method pattern is used in many parts of the framework (WinForms, WPF...)
  • The Builder pattern is also used quite often (DbConnectionStringBuilder, UriBuilder...)
  • I think the predefined instances (static properties) of StringComparer, Encoding, Color, etc are a variant of the Prototype pattern
  • The Proxy pattern is everywhere when you use .NET remoting
  • Events are a variant of the Observer pattern
  • The Iterator pattern is used in collections
  • The Strategy pattern is used, for instance, in cryptography classes

There are probably more examples, but that's all I can think of right now...


Also, NullObject

  • String.Empty;
  • EventArgs.Empty;


  • Visitor Pattern in ExpressionVisitor class (Syste.Linq.Expression namespace).
  • Adapter Pattern in System.Web.Abstractions - wrap up various Web classes (HttpRequest, HttpResponse) in a more unit testable way - i.e. HttpResponseBase.
  • Factory Method - Activator.CreateInstance - creates an instance of specified object.
  • Iterator pattern - all implementations of IEnumerable.


Some more GoF Design Patterns implemented in the .Net framework:

Façade - Higher level interface to a set of interfaces in a subsystem

MessageBox (System.Windows.Forms) - provides a reusable high level interface to some of the Windows Forms interfaces, instead of writing a whole lot of code to present a dialog you can just call MessageBox.Show("Hello world");.

This is also mentioned in Design Patterns in C# by Steven John Metsker:

The MessageBox class is one of the few examples of a facade in the FCL. It is production-worthy, configurable, and designed for reuse. Above all else, the MessageBox class fulfills the intent of the FACADE pattern by providing a simple interface that makes it easy to display dialogs.

If you want to know more check out the source code for MessageBox

Flyweight - Use sharing to support large numbers of fine-grained objects efficiently.

The .Net framework uses String Interning to save memory on identical strings, this is an implementation of the Flyweight pattern. This video by Curtis Lassam does a great job of explaining String Interning.

You can also force String Interning by calling String.Intern("Hello world");.


Prototype - Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.

ICloneable interface with method Clone() is classic example of prototype.


Provider pattern - used in MembershipProvider, RoleProvider, ProfileProvider.


Composite (object structural pattern) - Span objects of System.Windows.Documents group Inline objects while being Inline objects themselves.

Decorator (object structural pattern) - objects of classes derived from the Decorator class of System.Windows.Controls, described by the following definition:

Provides a base class for elements that apply effects onto or around a single child element, such as Border or ViewBox.

Singleton (object creational pattern) - the Application object returned by the Application.Current property of System.Windows. A description from its Remarks section:

Application is a per-AppDomain singleton type that implements the static Current property to provide shared access to the Application instance for the current AppDomain. This design guarantees that state managed by Application, including shared resources and state, is available from a single, shared location.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号