Design Patterns
Telerik Academy Alpha


HQC

 Table of contents

What is Design Pattern?

 What is Design Pattern?

  • General, repeatable and reusable solution to a common problem in software design

 What is not Design Pattern?

  • ­Not f inished design that can be transformed directly into code
     
  • ­Not code snippets
     
  • Not algorithms
     
  • Not components/libraries
     
  • Not language-specific

 When to use a Desing Pattern?

  • Solutions to problems that occur more times
     
  • Solutions that require several steps
    • Not all problems need all steps
    • Patterns can be overkill if a solution is a simple linear set of instructions!
       
  • Do not use a pattern only because you can
    • Overdesign is evil!

 Drawbacks

  • Patterns do not lead to a direct code reuse
     
  • Patterns are deceptively simple
     
  • Teams may suffer from pattern overload
     
  • Integrating patterns into the software development process is a human-intensive activity
     
  • Use patterns if you understand them well

Creational Design Patterns

 What?

  • Deal with object creation mechanisms
     

  • Trying to create objects in a manner suitable to the situation
     

  • Composed of two dominant ideas

    • Encapsulating knowledge about which concrete classes the system uses

    • Hiding how instances of these concrete classes are created and combined

Singleton

Singleton

Ensures single instance of an object for the project

 What is Singleton Design Pattern?

  • Class that is guaranteed to have only a single instance and provides global point of access to it

    • Examples: window manager, file system, console, application logger, state object

       

  • Encapsulated "just-in-time initialization" or "initialization on first use".

 When to use Singleton?

  • Different parts of a system need to access a single object
     

  • System requires global access to the object instance
     

  • Expensive instantiation -> lazy loading

 How to implement Singleton?

public Logger
{
    private static Logger instance;
    // private constructor ensures that
    // Logger cannot be instantiated from outside
    private Logger()
    { }
    // provide access to the single instance
    public static Logger Instance
    {
        get
        {
            // instantiate on the first access
            if(instance == null)
                instance = new Logger();

            return instance;
        }
    }
    public void Log(string log)
    {
        Console.WriteLine(log);
    }
}

 Problems

  • The Singleton design pattern is one of the most inappropriately used patterns
     

    • Designers frequently use Singletons in a misguided attempt to replace global variables
       

    • Singletons can make testing harder because they often rely on static methods and properties

Abstract Factory

Abstract Factory

Defines abstract interface for creating a family of related types of objects

 What is Abstract Factory?

  • Defines an abstract interface for creating a family of related types of objects
     

  • The created objects are returned as interface types or base types
     

  • Multiple factories can implement the abstract interface

 When to use Abstract Factory?

  • If an application is to be portable, it needs to encapsulate platform dependencies
     

  • Too often, this encapsulation is not engineered in advance, and lots of #ifdef case statements with options for all currently supported platforms begin to procreate like rabbits throughout the code

 How to implement Abstract Factory?

interface IContinentFactory { // AbstractFactory
   Herbivore CreateHerbivore();
   Carnivore CreateCarnivore();
}
class AfricaFactory : IContinentFactory {
   public Herbivore CreateHerbivore() {
      return new Wildbeаst();
   }
   public Carnivore CreateCarnivore() {
      return new Lion(); // Constructor can be internal
   }
}
class AmericaFactory : IContinentFactory {
    public Herbivore CreateHerbivore() {
        return new Bison();
    }
    public Carnivore CreateCarnivore() {
        return new Wolf();
    }
}

 Problems

  • This pattern can introduce a lot of accidental complexity

    • One of the main drawbacks is the extra complexity and writing the code during the initial stages
       

  • Does your application really need an Abstract Factory?

 Quizlet

  1. The console is/ is not an example of Singleton?
  2. Must Singleton objects be initialized with the start of the programme?
  3. Does Singleton facilitate testing?
  4. Abstract factory facilitates controlling the behavior of the objects?
  5. Must the client specify the way each object from the factory is created?
  6. Nice implementation of Abstract factory?
public abstract class AbstractFactory {
   abstract Color GetColor(String color);
   abstract Shape GetShape(String shape) ;
}
public class ShapeFactory: AbstractFactory {
   private override Shape GetShape(String shapeType){
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();  
      }     
      return null;
   }

   private override Color GetColor(String color) {
      return null;
   }
}

Structural Design Patterns

 What is Structural Design Pattern?

  • Describe ways to assemble objects to implement a new functionality
     

  • Simple way to realize relationships between entities
     

  • All about Class and Object composition

    • Structural class-creation patterns use inheritance to compose interfaces

    • Structural object-patterns define ways to compose objects to obtain new functionality

Composite

 Composite

Treat in the same way individual objects or groups of objects

 When to use Composite?

  • ­We have different objects and we want to treat them the same way
     

  • We want to present hierarchy of objects

    • Tree-like structures
       

  • Examples in .NET Framework

    • Windows.Forms.Control and its derived classes

    • System.Web.UI.Control and its derived classes

    • System.Xml.XmlNode and its derived classes

 How to implement Component?

abstract class MailReceiver 
{
    public abstract void SendMail();
}
class EmailAddress : MailReceiver 
{
    public override void SendMail() { /*...*/ }
}
class GroupOfEmailAddresses : MailReceiver 
{
    private List<MailReceiver> participants;
    public override void SendMail() 
    {
        foreach(var p in participants) 
        {
            p.SendMail();
        }
    }
}
static void Main()
{
    var rootGroup = new GroupOfEmailAddresses();
    rootGroup.SendMail();
}

Decorator

Decorator

Add functionality to existing objects at run-time

 What is Decorator Design Pattern?

  • Extends the original component
     
  • Alternative to inheritance (class explosion)
     

  • Support Open-Closed principle

    • Flexible design, original object is unaware

 When to use Decorator?

 When to use Decorator?

  • You want to add behavior or state to individual objects at run-time

  • Inheritance is not feasible because it is static and applies to an entire class

  • This flexibility can be achieved with the following design

 How to implement Decorator?

abstract class Decorator : LibraryItem {
    protected LibraryItem libraryItem;
    public Decorator(LibraryItem libraryItem) {
        this.libraryItem = libraryItem;
    }
    public override void Display() {
        libraryItem.Display();
    }
}
class Borrowable : Decorator {
    protected List<string> borrowers = new List<string>();
    public Borrowable(LibraryItem libraryItem) : base(libraryItem) {}
    public void BorrowItem(string name) {
      borrowers.Add(name);
      libraryItem.NumCopies--;
    }
    public override void Display() {
      base.Display();
      foreach (string borrower in borrowers) {
        Console.WriteLine(" borrower: " + borrower);
      }
    }
  }

​Decorator vs Inheritance

  1. Decorating can provide new behavior at runtime for individual objects, and the change affects all instances of the original class; Subclassing adds behavior at compile time
     
  2. Example: TextView class.
    1. You want a scrolled text view - ScrolledTextView class.
    2. You want a border around text view - BorderedTextView.
    3. You want both border and scroll - ScrolledBorderedTextView

      Result - duplication of the effort + class explosion

       
  3. Decorator pattern is used to decorate the existing classes without changing the old behavior.
     
  4. You can test your decorator in isolation of the decorated object (not possible with inheritance to mock the parent class)

Adapter

Adapter

Converts the given class'es interface into another class requested by the client

 What is Adapter Design Pattern?

  • Converts the given class' interface into another class requested by the client

    • Wraps an existing class with a new interface

    • Impedance match an old component to a new system
       

  • Allows classes to work together when this is impossible due to incompatible interfaces

 When to use Adapter?

  • An "off the shelf" component offers compelling functionality that you would like to reuse
     

  • But its "view of the world" is not compatible with the philosophy and architecture of the system currently being developed

 How to implement Adapter?

interface ITarget {
  List<string> GetProducts();
}
public class VendorAdaptee
{
   public List<string> GetListOfProducts() {
      List<string> products = new List<string>();
      products.Add("Gaming Consoles");
      products.Add("Television");
      products.Add("Books");
      products.Add("Musical Instruments");
      return products;
   }
}
class VendorAdapter:ITarget {
   public List<string> GetProducts() {
      VendorAdaptee adaptee = new VendorAdaptee();
      return adaptee.GetListOfProducts();
   }
}
class ShoppingPortalClient {
   static void Main(string[] args) {
      ITarget adapter = new  VendorAdapter();
      foreach (string product in adapter.GetProducts()) {
        Console.WriteLine(product);
      }
      Console.ReadLine();
   }
}

 Quizlet

  1. Composite pattern handles a single object and group of objects differently?

  2. Decorator pattern works in favour of keeping the Open-Closed principle?

  3. If you have an old class with API that does not work anymore which pattern are you going to use?

  4. Differences between Decorator pattern and inheritance?

  5. Adapter pattern creates new implementations of the objects of old system?

  6. The 'Adaptee' class is the one which interface is not compatible or the class that takes care of the implementing the new interface?

  7. The 'Target' class is?

8. Which design pattern is illustrated with:

Behavioral Design Patterns

 What is Behavioral Design Pattern?

  • Concerned with communication (interaction) between the objects

    • Either with the assignment of responsibilities between objects

    • Or encapsulating behavior in an object and delegating requests to it
       

  • Increase flexibility in carrying out cross-classes communication

Template Method

Template Method

The program skeleton of an algorithm in an operation, deferring some steps to subclasses

 What is Template method Design Pattern?

  • Defines the base of an algorithm in a method, leaving some implementation to its subclasses

  • Allows the subclasses to redefine the implementation of some of the parts of the algorithm

    • Doesn’t let the subclasses to change the algorithm structure

  • Relies on inheritance

    • Strategy on composition

  • Usually, override of virtual or abstract method (hook)

 When to use Template Method?

  • Two or more classes should follow the same common algorithm or workflow
     

  • The workflow never changes
     

  • Subclasses may redefine the steps (not order)
     

  • Some steps may be implemented in the base class (DRY)

     

 How to implement Template Method?

public abstract class HotDrink {
    public void PrepareRecipe()
    {
        BoilWater(); Brew(); PourInCup(); AddSpices();
    }
    protected abstract void Brew();
    protected abstract void AddSpices();
    private void BoilWater() { ... }
    private void PourInCup() { ... }
}
public class Coffee : HotDrink {
    protected override void Brew() { ... }
    protected override void AddSpices() { ... }
}
public class Tea : HotDrink {
    protected override void Brew() { ... }
    protected override void AddSpices() { ... }
}

Questions

[C# HQC] Design Patterns

By telerikacademy

[C# HQC] Design Patterns

  • 1,093