Design Pattern in. Net -- Strategy Pattern

Source: Internet
Author: User

Design Pattern in. Net -- Strategy Pattern

I. Mode Overview

"Interface-oriented programming" is the most important principle in object-oriented programming. According to the principle of "encapsulation change", we often abstract and define the easy-to-change part as an interface. The caller only needs to know the external definition of the interface. In the design pattern, the Strategy pattern is the best embodiment of "interface-Oriented Programming". Part of its abstraction is specific "algorithms" or "policies ".
Suppose we want to develop a tax system, then the tax calculation will be divided into personal income tax and corporate income tax according to different taxpayers, these two types of taxes are different in calculation methods. Now, we can use the policy mode to abstract the tax policy into the interface ITaxStrategy:
Public interface ITaxStrategy
{
Double Calculate (double income );
}
After the tax calculation policy is abstracted, the coupling between modules is eliminated from the design, eliminating the possibility of large-scale system modifications in the future, the so-called "interface-oriented programming" is based on this principle.
After an interface is defined, various tax policies implement this interface:
Public class PeronalTaxStrategy: ITaxStrategy
{
Public double Calculate (double income)
{
// Implementation;
}
}
Public class EnterpriseTaxStrategy: ITaxStrategy
{
Public double Calculate (double income)
{
// Implementation;
}
}
If there is a public class at this time, tax-related operations are provided, including the method for calculating income tax:
Public class TaxOp
{
Private ITaxStrategy m_strategy;
Public TaxOp (ITaxStrategy strategy)
{
This. m_strategy = strategy;
}
Public double GetTax (double income)
{
Return strategy. Calculate (income );
}
}
In this class, an ITaxStrategy object is received. Because this object is an interface type, the TaxOp class is irrelevant to specific tax policies, they become a weak dependency relationship due to the introduction of interfaces, as shown in the class diagram:
 
If the client needs to call tax-related operations, the Tax Policy object can be instantiated Based on the taxpayer type:
Public class App
{
Public static void Main (string [] args)
{
TaxOp op = new TaxOp (new PersonalTaxStrategy ());
Console. WriteLine ("The Personal Tax is: {0}", op. GetTax (1000 ));
}
}

Ii. Strategy Mode in. Net Framework

The Stragety mode is widely used, and there are naturally many application examples in. Net Framework. For example, in. Net, the sort function provided for Array and ArrayList of Collection types uses the Strategy Mode in its implementation. It encapsulates the comparison algorithm and defines the IComparer interface. Classes that implement the IComparer interface can be ordered or compared to the size of two objects in reverse order.
In addition, in the System. Configuration. Provider namespace, many Strategy modes are introduced under the inheritance System of Provider. In this namespace, an abstract class ProviderBase is defined. Its definition is simple. It only includes an initialized virtual method and several virtual attributes. The following code:
Public abstract class ProviderBase
{
// Methods
Protected ProviderBase ();
Public virtual void Initialize (string name, NameValueCollection config );

// Properties
Public virtual string Description {get ;}
Public virtual string Name {get ;}

// Fields
Private string _ Description;
Private bool _ Initialized;
Private string _ name;
}
ProviderBase has many derived classes, including System. configuration. protectedConfigurationProvider, System. configuration. settingProvider, System. web. security. roleProvider, System. web. security. membershipProvider and so on. However, these derived subclasses are all abstract classes. They have their own inheritance systems and have the characteristics of the Strategy Mode. Take RoleProvider as an example. First, let's look at the definition of RoleProvider in. Net Framework:
Public abstract class RoleProvider: ProviderBase
{
// Methods
Protected RoleProvider ();
Public abstract void AddUsersToRoles (string [] usernames, string [] roleNames );
Public abstract void CreateRole (string roleName );
Public abstract bool DeleteRole (string roleName, bool throwOnPopulatedRole );
Public abstract string [] FindUsersInRole (string roleName, string usernameToMatch );
Public abstract string [] GetAllRoles ();
Public abstract string [] GetRolesForUser (string username );
Public abstract string [] GetUsersInRole (string roleName );
Public abstract bool IsUserInRole (string username, string roleName );
Public abstract void RemoveUsersFromRoles (string [] usernames, string [] roleNames );
Public abstract bool RoleExists (string roleName );

// Properties
Public abstract string ApplicationName {get; set ;}
}
In the RoleProvider abstract class, there is no specific implementation, all of which are abstract methods. At this time, the abstract class is actually no different from the interface (note: in fact, in WebLogic, In the role management API, define RoleProvider as an interface ). To facilitate understanding of the design concept, we simplify the RoleProvider class and focus only on the CreateRole () abstract method of this class.
There are many types of RoleProvider abstract classes, such as AuthorizationStoreRoleProvider, SqlRoleProvider, and window#enroleprovider. Therefore, the final implementation class diagram should be as follows:
 
Subclass override the abstract method of the parent class RoleProvider, such as SqlRoleProvider:
Public class SqlRoleProvider: RoleProvider
{
Public override void CreateRole (string roleName)
{
// Implementation;
}
}
RoleProvider is used in ASP. NET. It is usually configured in the web. config configuration file. For example, configure RoleProvider in the RoleManager section:
<RoleManager defaultProvider = "SqlProvider" enabled = "true">
<Providers>
<Add name = "SqlProvider"
Type = "System. Web. Security. SqlRoleProvider"
ConnectionStringName = "SqlServices"
ApplicationName = "PatternsSample"/>
</Providers>
</RoleManager>
In the configuration file, when processing in. Net, providers must be of the RoleProvider type, and then bind it to a specific RoleProvider by setting the type value. The disposal method here clearly uses the Dependency Injection (Dependency Injection) technology and reflection technology to inject SqlRoleProvider object sqlProvider, which avoids the creation of specific SqlRoleProvider objects, removes the coupling between the caller and the caller. Of course, in the configuration file, RoleProvider must be used with Membership, but this is not the focus of attention here, so we will not explain it in detail.
The same design method as RoleProvider. In. Net Framework, MemberShipProvider also utilizes the Strategy mode, as shown in the design structure:
 
SqlMembershipProvider is a common type, which provides Membership management for SQL Server. To provide Oracle Database Support for Membership, we can customize a class to inherit MembershipProvider:
Public class OracleMembershipProvider: MembershipProvider
{
// Implementation;
}
In the. Net Framework, a typical Strategy mode is used, that is, the IConfigurationSectionHandler interface:
Public interface IConfigurationSectionHandler
{
Object Create (object parent, object configContext, XmlNode section );
}
This interface contains only one method, namely the Create () method. We can understand it as an algorithm for creating the configuration section, the classes that implement this interface include DictionarySectionHandler, IgnoreSectionHandler, NameValueSectionHandler, and so on, which correspond to the creation types of various configuration Sections respectively. In addition, we can also define a class to implement this interface, for example:
Public class CustomHandler: IConfigurationSectionHandler
{
Public object Create (object parent, object configContext, XmlNode section)
{
// Implementation;
}
}
From the class diagram, we can see that it is very consistent with the features of the Strategy Mode:
 
Although in. Net2.0, The IConfigurationSectionHandler type object has been set as obsolete by the ObsoleteAttribute and replaced by the implementation of the ConfigurationSection, this design idea is still worth learning.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.