65.9K
CodeProject 正在变化。 阅读更多。
Home

策略

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2013 年 10 月 11 日

CPOL

3分钟阅读

viewsIcon

10139

策略设计模式允许你可互换地使用多种算法。你使用策略模式的一个原因是

策略

策略设计模式允许你可互换地使用多种算法。

使用策略模式的一个原因是简化过于复杂的算法。有时,随着算法不断演化以处理越来越多的情况,它可能会变得非常复杂且难以维护。将这些复杂的算法分解为更小、更易于管理的算法,可以使你的代码更具可读性,并且更容易维护。 作为一个简单的策略模式实现示例,请考虑以下场景。

一个软件系统使用单个授权检查类来确定系统内的访问权限。匿名用户、登录用户和系统管理员的访问权限将不同。

当然,我们可以在单个类中处理这 3 种不同的访问级别,但是如果添加第四种类型的访问级别,甚至第五种呢?让我们将每个访问检查分解为它自己的策略对象,我们可以根据系统中登录的用户类型可互换地使用这些对象。

首先,我们需要定义一个接口,所有策略类都将实现该接口。通过实现此接口,我们的策略类才能可互换地使用。

Public Interface IAuthorityCheck
    Function IsAuthorized(ByVal resource As Object) As Boolean
End Interface 

定义了一个简单的接口后,我们可以创建任何数量的不同类来实施该接口,并为我们执行安全检查。以下是代表我们的策略类的 3 个示例。

首先,对于我们的匿名用户,我们创建一个始终返回 False 的安全策略类。

Public Class AnonymousSecurityCheckStrategy
    Implements IAuthorityCheck

    Public Function IsAuthorized(ByVal resource As Object) As Boolean Implements IAuthorityCheck.IsAuthorized
        'when checking access rights, anonymous users will
        'always be denied access to all resources
        Return False
    End Function
End Class

接下来是我们的登录用户。他们也需要一个策略来确定他们的访问权限。

Public Class StandardSecurityCheckStrategy
    Implements IAuthorityCheck

    Public Function IsAuthorized(ByVal resource As Object) As Boolean Implements IAuthorityCheck.IsAuthorized
        'based on the current users credentials
        'examine the object and determine if the user is allowed to access it
        Dim result As Boolean = PerformSomeApplicationSpecificSecurityChecks(resource)
        Return result
    End Function
End Class

最后,我们有我们的系统管理员。他们可以访问所有内容,因此他们获得一个始终返回 True 的策略。

Public Class SysAdminSecurityCheckStrategy
    Implements IAuthorityCheck

    Public Function IsAuthorized(ByVal resource As Object) As Boolean Implements IAuthorityCheck.IsAuthorized
        'The System Administrator will be granted access to all secure resources
        Return True
    End Function
End Class

现在,我们只需要在运行时选择其中一个策略对象并调用 IsAuthorized 方法。为了可互换地使用这些类,我们将针对接口 IAuthorithyCheck 进行编码,而不是针对实际的具体的类类型。

一种选择特定策略的方法是使用 工厂。该 工厂 将封装确定我们各种策略类中哪个是正确使用的所有必要逻辑。例如

Public Class AuthorizationStrategyFactory
    'To avoid the need to repeat the logic required to select the correct Strategy object
    'we will encapsulate that logic in a small Factory class
    Public Shared Function GetAuthorizationStrategy() As IAuthorityCheck
        'This method returns 1 of 3 different algorithms for performing authorizations

        'sysadmins gets the Strategy object that always allows access
        If currentUserObject.IsInRole("sysadmin") Then Return New SysAdminSecurityCheckStrategy

        If currentUserObject.LoggedIn = True Then
            'Logged in users (non-sysadmin) get a Strategy object that performs various security checks
            Return New StandardSecurityCheckStrategy
        Else
            'All other users are considered Anonymous
            'These users are given a Strategy object that always disallows access
            Return New AnonymousSecurityCheckStrategy
        End If
    End Function
End Class

策略对象就位,并且有一个 工厂 来为我们创建正确的策略对象,执行授权检查就变得很简单了

'coding against the Interface we created
Dim authorityCheck As IAuthorityCheck

'ask the Factory for the Strategy object
authorityCheck = AuthorizationStrategyFactory.GetAuthorizationStrategy()

'at this point we have been returned 1 of the 3 strategy objects
'we do not know which one, and we do not need to know which one

'perform authorization check
If authorityCheck.IsAuthorized(someResourceObject) = False Then
    'abort - user not authorized
Else
    'proceed - user was authorized
End If

现在,如果需要第四种类型的访问权限(JuniorSysAdminEverythingButPayrollAccess),我们可以创建一个新的 Strategy 类来实现我们的接口,并包含适用于新的安全检查的特定算法。然后,我们将修改 Factory 类,以便在适当的时候返回该新的 Strategy 对象。调用 IsAuthorized 方法的最后一点代码无需更改。

这里的示例可能有点牵强,但我希望它能说明实施策略模式的机制。

另外,请注意,ASP.NET 2.0 中引入的 提供程序模型 是基于策略设计模式的。

示例:C# 中的策略设计模式。

1. GoAlgorithm (接口)

namespace DesignPatterns.StrategyDP {
 
interface GoAlgorithm {
  
             void go();
   }
2. GoByFlyingAlgorithm (类)
class GoByFlyingAlgorithm: GoAlgorithm {

        public void go() {

            Console.WriteLine("Now I'm Flying"); 

        }

    }
3. GoByDrivingAlgorithm (类)
class GoByDrivingAlgorithm: GoAlgorithm {
        
     public void go() {

            Console.WriteLine("Now I'm Driving."); 

        }

    } 

你可以定义更多的算法,例如 “GoByMotorBikeAlgoritm” 等。

class GoByMotorBikeAlgoritm: GoAlgorithm {

     public void go() {

             Console.WriteLine("Now I'm Riding");         

         }
}

4. Vehicle (抽象类)

abstract class Vehicle {
 
        private GoAlgorithm goAlgorithml;

        public void setAlgorithm(GoAlgorithm Algorithm_Name) {
  
            goAlgorithml = Algorithm_Name;
        }

        public void go() {
  
            goAlgorithml.go();
   
        }
    }

5. 车辆类型,如 'Car'、'Vehicle' 和 'Bike'

class Car: Vehicle {
      
         public  Car() {
            setAlgorithm(new GoByDrivingAlgorithm());
        }

    }

class Helicopter:Vehicle {

        public Helicopter() {
  
            setAlgorithm(new GoByFlyingAlgorithm());
   
        }

    }

class Bike:Vehicle {

        public Helicopter() {
  
            setAlgorithm(new GoByMotorBikeAlgoritm());
   
        }

    }

6. Main

 class Program {
       
  static void Main(string[] args) {
           
   /* Strategy Design Patterns*/
           
            Car F1car = new Car();
            Helicopter Choper = new Helicopter();
            Bike HeroHonda = new Bike();

            F1car.go();
            Choper.go();
            HeroHonda.go(); 

        }
    }
© . All rights reserved.