GoF: Template Method Pattern

ความตั้งใจ

Template Method ช่วยให้การทำงานที่เป็น step มีขั้นตอน หรือ algorithm ที่เป็นต้นแบบแน่นอนอยู่แล้ว(program sigleton)ให้ subclass ทำตาม step นี้เสมอได้อย่างง่ายๆ โดยการแสดงพฤติกรรมภายในของ subclass สามารถเปลี่ยนแปลงไปตามคุณลักษณะของตัวมันเองได้(polymorphism)

ประยุกต์ใช้

การประยุกต์ Template Method กับ  Automate Unit Testing ที่จะต้องมีการดำเนินการเป็นขั้นตอน ที่แน่นอนอยู่แล้ว ตามลำดับ ดังนี้ Setup -> Exercise -> Verify -> Teardown

เขียนเป็นแผนภาพ UML Class diagram ของ automate unit testing โดยประยุกต์ใช้ Template Method ได้ตามนี้

เขียน Code ได้ตามนี้

public abstract class AutomateUnitTestTemplateMethod
{
  private event Action CommonMethodSetToExecute;

  public abstract Action Setup { get;}
  public abstract Action Exercise { get;}
  public abstract Action Verify { get; }
  public abstract Action Teardown { get; }

  public AutomateUnitTestTemplateMethod()
  {
    CommonMethodSetToExecute = Setup + Exercise + Verify + Teardown;
  }

  public Action DoTest
  {
    get { return CommonMethodSetToExecute; }
  }
}

ผมสมมุติ class เป้าหมายเพื่อใช้สำหรับทดสอบ กับ automate unit testing template method

public class MyCal
{
  public Func<int, int, int> Add
  {
    get{ return (a, b) => checked(a + b);}
  }
}

ตัวอย่างนี้ผมสมมติ subclass ที่เป็น AutomateUnitTestTemplateMethod 2 Class คือ class ทดสอบ method Add 10 กับ 20 โดยคาดหวังผลเท่ากับ 30 และ Class automate ทดสอบ method Add MAX ของ int กับ 1 ซึ่งผมคาดหวังผลคือ exception Overflow ครับ(บวกเกิน int มันต้องเกิด exception ว่างั้น)

public class TestMyCalAdd_10_20 : AutomateUnitTestTemplateMethod
{
  MyCal ObjectUnderTest;
  int ExpectedValue;
  int RealValue;

public override Action Setup
{
  get
  {
    return () =>
    {
      ObjectUnderTest = new MyCal();
      ExpectedValue = 30;
      RealValue = 0;
    };
  }
}

public override Action Exercise
{
  get
  {
    return () => RealValue = ObjectUnderTest.Add(10, 20);
  }
}

public override Action Verify
{
  get
  {
    return () =>
    {
      if (ExpectedValue != RealValue)
        Console.WriteLine("Fail. Expected value {0} but {1}", ExpectedValue, RealValue);
      else
        Console.WriteLine("Pass.");
    };
  }
}

public override Action Teardown
{
  get
  {
    return () =>
    {
      ObjectUnderTest = null;
      ExpectedValue = 0;
      RealValue = 0;
    };
  }
}
}
public class TestMyCalAdd_MAX_1 : AutomateUnitTestTemplateMethod
{
MyCal ObjectUnderTest;
Type ExpectedValue;
Type RealValue;

public override Action Setup
{
get
{
return () =>
{
ObjectUnderTest = new MyCal();
ExpectedValue = typeof(OverflowException);
RealValue = null;
};
}
}

public override Action Exercise
{
get
{
return () =>
{
try
{
int a = ObjectUnderTest.Add(int.MaxValue, 1);
}
catch (OverflowException ex)
{
RealValue = ex.GetType();
}
};
}
}

public override Action Verify
{
get
{
return () =>
{
if (RealValue != ExpectedValue)
Console.WriteLine("Fail. Expected value {0} but {1}", ExpectedValue, RealValue);
else
Console.WriteLine("Pass.");
};
}
}

public override Action Teardown
{
get
{
return () =>
{
ObjectUnderTest = null;
ExpectedValue = null;
RealValue = null;
};
}
}
}

และ code ทดสอบ ของทั้ง TestMyCalAdd_10_20 และ TestMyCalAdd_MAX_1 คือ
[TestMethod]
public void TestTemplateMethodPattern()
{
AutomateUnitTestTemplateMethod testcase1 = new TestMyCalAdd_10_20();
testcase1.DoTest();//Pass

AutomateUnitTestTemplateMethod testcase2 = new TestMyCalAdd_MAX_1();
testcase2.DoTest();//Pass
}

เสร็จแล้วครับกับ Template Method Pattern เป็น 1 ใน 23 pattern ของ GoF มันจะอยู่ในหมวดของ Behavioral Patterns ตัวอย่างประยุกต์ Template method pattern ที่นิยมใช้มากคือ Game Engine loop , Business Automate system เป็นต้น

ขอบคุณครับ 🙂

ไม่หล่อ แต่ต้องมี style

— Chav:P —

Advertisements

#design-patterns, #gof