小猪学设计模式——模板方法模式

前言

在小猪之前写的代码中有这样的功能:在需要验证的页面中加入逻辑的验证

public void page_load(obeject sender, event e)

{

    if(Session["admin"]==null||Session["admin"]=="")

    {

        //跳转到登陆页

    }

    //继续操作

}

 

而在每个页面中都需要加入这样的逻辑判断来验证用户是否登陆。

同样在ASP.NET MVC里面需要在每个Action里面加入这样的判断。

而后来小猪写了多了就发现不应该在每个页面里面都写上这样同样的代码,可以写在一个基类里面然后需要验证的时候(页面)继承自这个类就实现了同样的效果,而且是一劳永逸。其实这就类似于模板方法模式的思想了,只是当时小猪并没有意识到而已。

模式定义

所谓模板方法模式就是在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法模式是基于继承的代码复用技术的。在模板方法模式中,我们可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中。也就是说我们需要声明一个抽象的父类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法让子类来实现剩余的逻辑,不同的子类可以以不同的方式来实现这些逻辑。
其实所谓模板就是一个方法,这个方法将算法的实现定义成了一组步骤,其中任何步骤都是可以抽象的,交由子类来负责实现。这样就可以保证算法的结构保持不变,同时由子类提供部分实现。
模板是一个方法,那么他与普通的方法存在什么不同呢?模板方法是定义在抽象类中,把基本操作方法组合在一起形成一个总算法或者一组步骤的方法。而普通的方法是实现各个步骤的方法,我们可以认为普通方法是模板方法的一个组成部分。

模板方法模式就两个角色:
AbstractClass: 抽象类
ConcreteClass:  具体子类
其中抽象类提供一组算法和部分逻辑的实现(例如:实现了验证是否登陆),具体子类实现剩余逻辑。

代码实现

下面的代码模拟演示了两个相同的学生做相同的题目的过程。其中代码一是最简单也是没有采用任何模式的写法,代码二则使用了比较好的模板方法模式。无疑,代码一中在两个类中复制了大量的相同代码,不仅不好看而且增加了程序的维护难度。

代码清单一:

class Program

{

    static void Main(string[] args)

    {

        Console.WriteLine("学生甲抄的试卷:");

        TestPaperA studentA = new TestPaperA();

        studentA.TestQuestion1();

        studentA.TestQuestion2();

        studentA.TestQuestion3();

  

        Console.WriteLine("学生乙抄的试卷:");

        TestPaperB studentB = new TestPaperB();

        studentB.TestQuestion1();

        studentB.TestQuestion2();

        studentB.TestQuestion3();

  

        Console.Read();

    }

}

  

//学生甲抄的试卷

class TestPaperA

{

    //试题1

    public void TestQuestion1()

    {

        Console.WriteLine(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");

        Console.WriteLine("答案:b");

    }

    //试题2

    public void TestQuestion2()

    {

        Console.WriteLine(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");

        Console.WriteLine("答案:a");

    }

    //试题3

    public void TestQuestion3()

    {

        Console.WriteLine(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");

        Console.WriteLine("答案:c");

    }

  

  

}

  

//学生乙抄的试卷

class TestPaperB

{

    //试题1

    public void TestQuestion1()

    {

        Console.WriteLine(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");

        Console.WriteLine("答案:d");

    }

    //试题2

    public void TestQuestion2()

    {

        Console.WriteLine(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");

        Console.WriteLine("答案:b");

    }

    //试题3

    public void TestQuestion3()

    {

        Console.WriteLine(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");

        Console.WriteLine("答案:a");

    }

  

}

代码清单二:

class Program

{

    static void Main(string[] args)

    {

        Console.WriteLine("学生甲抄的试卷:");

        TestPaper studentA = new TestPaperA();

        studentA.TestQuestion1();

        studentA.TestQuestion2();

        studentA.TestQuestion3();

  

        Console.WriteLine("学生乙抄的试卷:");

        TestPaper studentB = new TestPaperB();

        studentB.TestQuestion1();

        studentB.TestQuestion2();

        studentB.TestQuestion3();

  

        Console.Read();

  

    }

}

  

class TestPaper

{

    public void TestQuestion1()

    {

        Console.WriteLine(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");

        Console.WriteLine("答案:" + Answer1());

    }

  

    public void TestQuestion2()

    {

        Console.WriteLine(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");

        Console.WriteLine("答案:" + Answer2());

    }

  

    public void TestQuestion3()

    {

        Console.WriteLine(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");

        Console.WriteLine("答案:" + Answer3());

    }

  

    protected virtual string Answer1()

    {

        return "";

    }

  

    protected virtual string Answer2()

    {

        return "";

    }

  

    protected virtual string Answer3()

    {

        return "";

    }

  

  

}

//学生甲抄的试卷

class TestPaperA : TestPaper

{

    protected override string Answer1()

    {

        return "b";

    }

  

    protected override string Answer2()

    {

        return "c";

    }

  

    protected override string Answer3()

    {

        return "a";

    }

}

//学生乙抄的试卷

class TestPaperB : TestPaper

{

    protected override string Answer1()

    {

        return "c";

    }

  

    protected override string Answer2()

    {

        return "a";

    }

  

    protected override string Answer3()

    {

        return "a";

    }

  

}

 

模式优缺点
           优点
             1、模板方法模式在定义了一组算法,将具体的实现交由子类负责。
             2、模板方法模式是一种代码复用的基本技术。
             3、模板方法模式导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。
         缺点
            每一个不同的实现都需要一个子类来实现,导致类的个数增加,是的系统更加庞大。

使用场景
            1、  一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
            2、  各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
            3、控制子类的扩展。

模式总结
            1、  模板方法模式定义了算法的步骤,将这些步骤的实现延迟到了子类。
            2、  模板方法模式为我们提供了一种代码复用的重要技巧。
            3、  模板方法模式的抽象类可以定义抽象方法、具体方法和钩子。
            4、  为了防止子类改变算法的实现步骤,我们可以将模板方法声明为final。

你可能感兴趣的:(设计模式)