Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro .NET 2.0 Code And Design Standards In CSharp (2006) [eng]

.pdf
Скачиваний:
34
Добавлен:
16.08.2013
Размер:
3.43 Mб
Скачать

246C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

class Client

{

static void Main(string[] args)

{

Subject observedAssemblyLine = new Subject(); Observer observerCarDealer = new

Observer("CarDealer Observer");

Observer observerDelivery = new Observer("Delivery Observer"); observerCarDealer.ObservedObject = ObservedAssemblyLine;

observerDelivery.ObservedObject = ObservedAssemblyLine; observerCarDealer.Attach(); observerDelivery.Attach(); observedAssemblyLine.InterestingData = "# 001

is now finished!"; observerCarDealer.Detach();

observedAssemblyLine.InterestingData = "# 002 is now finished!";

}

}

Console Output

Notification to CarDealer Observer, the car # 001 is now finished!

Notification to Delivery Observer, the car # 001 is now finished!

Notification to Delivery Observer, the car # 002 is now finished!

Press any key to continue

The Standard: Observer Design Pattern

The standard acknowledges the use of the Observer design pattern where there is a requirement to initiate and manage communications among a society of objects.

Strategy Pattern

A Strategy pattern encapsulates a design feature where there is a need to contextually manage different implementations of a concept. In everyday life, examples of a Strategy pattern include a chain of international hotels that applies a regional decor strategy; or a university that administers a course entrance strategy based on a set of business rules.

C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

247

What

A Strategy pattern is a design that presents a family of algorithms or business rules encapsulated in classes that can be swapped, polymorphically, within a context, which is independent of the client.

Where

A Strategy pattern is used where there is a design problem that requires the contextual implementation of different algorithms or business rules without the use of conditional code.

Why

In many domains there is a need to contextually apply a set of algorithms or business rules, and over time, as business requirements change, code that manages the choice and the implementation of algorithms or business rules can evolve into a tangled mess. The Strategy pattern prevents or overcomes this problem by presenting a design that separates the choice of algorithm or business rule from its implementation and delegates the contextual choice of algorithm or business rule to client code.

How

Design an abstract strategy class that includes an abstract method from which an algorithm may be called. For each strategy, subclass it from the abstract strategy class, then implement an appropriate algorithm in each of the concrete strategy classes. Prepare a context class to contain an abstract strategy class and then code the client to choose the strategy and inform the context class of the choice of strategy. Note that the context class acts as a liaison between the client and the strategy classes.

Pattern Example

In the Model T domain, there is client code that manages the task of handling inquiries regarding credit policy. For illustrative purposes, there is a credit policy context within which operates a credit strategy that seeks to offer favorable terms to volume purchasers (dealer and corporate customers). There are two different business rules or algorithms—one for each strategy (a corporate and a dealer strategy).

The part of the problem we are focusing on is how to apply the Strategy pattern to prevent the business rules from becoming intertwined in the choice of present and future strategies. This is tackled by implementing business rules in instances of strategy classes (objects), passing them, polymorphically, to a context class, which leverages composition to access the functionality of a strategy object. This allows client code to make the choice of which strategy to call or instantiate. That is the Strategy pattern!

We shall now look at the Strategy pattern in a UML diagram (see Figure 12-3) and then implement the pattern in code.

248C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

UML

Figure 12-3. Strategy pattern

Key Code Ingredients

The code for the Strategy pattern has the following key ingredients:

An abstract strategy class (Strategy), which contains an abstract or virtual method (CreditBusinessRule) to access the algorithm or business rule

A number of strategy classes derived from the abstract strategy class

An override, in the strategy classes (CorporateStrategy and DealerStrategy), of the method (CreditBusinessRule) that contains the algorithm or business rule

A context class (CreditSalesContext), which includes

a member variable that is of type abstract strategy class;

a method that represents an algorithm or business rule of a strategy that can be accessed by client code;

a constructor that is passed a strategy type.

Client code that makes the choice of which strategy to call or instantiate.

C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

249

Strategy Pattern Code

The essence of the design lies in specializing a set of Strategy classes that can be passed poly- morphically—because they all derive from Strategy—to a context class. It is the client which determines the context, by calling a given Context class. Notice that the Strategy class is abstract and that its only method (CreditBusinessRule()) is also abstract; that signifies that there is no default implementation in the abstract class, although that need not be the case. There may be default behavior implemented in the abstract class, but the business rule needs to be abstract or virtual so that it can be overridden in each Strategy subclass. In the case of a virtual method, if it is not overridden by any subclass, then this indicates that the Strategy pattern is an inappropriate design solution—the Strategy pattern is a design solution appropriate to situations where there is variation in business rules (algorithms).

Strategy Class

public abstract class Strategy

{

//abstract method which subclasses will

//implement to enable access to the strategy functionality public abstract void CreditBusinessRule();

public Strategy() {;}

}

CorporateStrategy Class

public class CorporateStrategy: Strategy

{

public override void CreditBusinessRule()

{

Console.WriteLine("Corporates: Allow 30 days credit.");

}

public CorporateStrategy() {;}

}

DealerStrategy Class

public class DealerStrategy: Strategy

{

public override void CreditBusinessRule()

{

Console.WriteLine("Dealers: Allow 90 days credit.");

}

public DealerStrategy() {;}

}

250C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

CreditSalesContext Class

public class CreditSalesContext

{

Strategy aStrategy;

public CreditSalesContext (Strategy crStrategy)

{

this.aStrategy = crStrategy;

}

public void BusinessRule()

{

this.aStrategy.CreditBusinessRule();

}

}

Client Code

In the client code, we see the Strategy pattern at work. We test the effectiveness of the design pattern by enabling the client code to choose a strategy in a given context.

class Client

{

static void Main(string[] args)

{

//Client makes choice to call the Corporate Strategy - there //is an inquiry from a potential corporate customer regarding //the credit terms.

CreditSalesContext cr = new CreditSalesContext(new CorporateStrategy()); cr.BusinessRule();

}

}

Console Output

Corporates: Allow 30 days credit.

Press any key to continue

The Standard: Strategy Design Pattern

The standard acknowledges the use of the Strategy design pattern where there is a design problem that requires the contextual implementation of different algorithms or business rules without the use of conditional code.

C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

251

Template Method Pattern

A Template Method pattern encapsulates a design feature, in an abstract class, which contains a template of an algorithm, part of which is left to be implemented by the subclass. In everyday life, examples of a Template Method pattern include a bank account application form, such that different accounts include a mix of standard questions and a few account-specific questions; or a book binder who binds all books in a given way but varies the algorithm or technique on limited editions.

What

A Template Method pattern ensures that the same structure can be subclassed to house different implementations of an algorithm and defer part of the implementation to the subclass.

Where

A Template Method pattern is used where there is a requirement for a common structure to house an algorithm, while offering some flexibility to vary the implementation of the algorithm.

Why

In many domains, there is a requirement for client code to call a common interface with a default implementation that has the flexibility for a subclass to vary the underlying algorithm within the implementation.

How

An abstract class exposes a Template Method that wraps a set of functionality or methods, part of which is overridden by a subclass.

Pattern Example

In the Model T domain, we have client code that manages the task of calling code to arrange the clock faces of different types of clocks that are fitted by a coachbuilder to the car. A requirement of the client code is that it wants a standard way to deal with this process regardless of the clock type—it simply wants to instantiate a clock type and call one method (SetupClockFace()). However, a design problem lies with the fact that not all clock faces are assembled in the same way; for example, a deluxe clock face has a label affixed to it, requiring one more step than needed to prepare a standard clockface, which doesn’t have a label.

The part of the problem we are focusing on is how to satisfy the requirements of a common code structure, which the client code expects, and yet permit the clock itself to implement its own functionality.

To code this routine we develop an abstract clock class—the clock needs to perform two steps to set up the clock face. The first step is to set the clock hands to seven, which is a requirement of all clocks (seven is an arbitrary number). The second step is to position a label on the clock face. The Standard clock face does not require a label; however, to accommodate this variability, the Clock class declares the method PositionLabel() as abstract, which requires a subclass to provide an implementation. In this example, the Deluxe clock will provide an implementation, whereas the Standard clock will provide a code stub (empty code). The method that

252C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

acts as a template is SetupClockFace(), which resides in the Clock class. Notice that Step 1 is a fixed task that is handled for the subclasses by the base class Clock, but Step 2 is delegated to the subclasses to implement. That is the Template Method pattern!

We shall now look at the Template Method pattern in a UML diagram (see Figure 12-4) and then implement the pattern in code.

UML

Figure 12-4. Template Method pattern

Key Code Ingredients

The code for the Template Method pattern has the following key ingredients:

An abstract base class (Clock)

An abstract method (PositionLabel())

A template method (SetupClockFace()), which resides in the base class and wraps several steps or other methods of the class

Any number of subclasses (ClockDeluxe and ClockStandard) that override the abstract method (PositionLabel()) called by the template method (SetupClockFace()) from the base class

Now let’s code the Template Method pattern.

C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

253

Template Method Code

The essence of the design lies in the use of inheritance to subclass a common interface and the structure of the algorithm contained within the template method (SetupClockFace()) in the base class (Clock). Notice that in the template method there is default behavior in the algorithm; however, within the algorithm lies the flexibility to vary an element of the algorithm—PositionLabel().

Clock Class

public abstract class Clock

{

//an abstract method that all sub-classes need to code a full

//implementation of functionality

public abstract void PositionLabel();

//the template method public void SetupClockFace()

{

//step 1. set hands to 7 o'clock - this could be represented as a method Console.WriteLine("Clock hands set at 7 o'clock");

//step 2. position the label on the clockface this.PositionLabel();

}

public Clock() {;}

}

Deluxe Clock Class

public class ClockDeluxe: Clock

{

public override void PositionLabel()

{Console.WriteLine("Deluxe clock, position the label bottom center.");} public ClockDeluxe() {;}

}

Standard Clock Class

public class ClockStandard: Clock

{

//A Standard clock has no label, so the code that positions a label is not required public override void PositionLabel() {;}

public ClockStandard() {;}

}

254C H A P T E R 1 2 B E H AV I O R A L P R O B L E M S

Client Code

In the client code, we see the Template Method pattern at work. We test the effectiveness of the design pattern by instructing the client code to instantiate a standard clock and a deluxe clock, and to call their respective SetupClockFace() methods. The template code, which resides in the base class (Clock), is implemented differently by the algorithm contained in the template method (SetupClockFace()) of the two subclasses (ClockDeluxe and ClockStandard).

class Client

{

static void Main(string[] args)

{

//create an instance of the deluxe clock //and set up the clockface Console.WriteLine("** A DELUXE CLOCK **"); Clock delClock = new ClockDeluxe(); delClock.SetupClockFace();

//create an instance of the standard clock //and set up the clockface Console.WriteLine("** A STANDARD CLOCK **"); Clock stdClock = new ClockStandard(); stdClock.SetupClockFace();

}

}

Console Output

** A DELUXE CLOCK **

Clock hands set at 7 o'clock

Deluxe clock, position the label bottom center. ** A STANDARD CLOCK **

Clock hands set at 7 o'clock Press any key to continue

The Standard: Template Method Design Pattern

The standard acknowledges the use of the Template Method design pattern where there is a requirement for a common structure to house an algorithm while offering some flexibility to vary the implementation of the algorithm.

P A R T 4

■ ■ ■

References

This part of the book includes the appendix, standards index, glossary, and index.

Соседние файлы в предмете Программирование на C++