前言:笔者在最开始写程序的时候经常会遇到一种情况,例如更改一个字段、或者添加一种小功能,就要把原来写过的东西几乎废弃掉,或者更改大量以前写过的代码。又或者自己写的东西时间久了再去回顾,完全找不到到时为什么这么写的头绪,如果遇到了Bug更是无法快速定位在哪里小范围出现的问题。如果你也经常遇到这种问题,就说明你现阶段非常需要学习下设计模式了。
在网上经常说的设计模式有23种,也有一些更多的设计模式,无非也是从这些设计模式中变种而来。如果让笔者来形容什么是设计模式,我认为设计模式是:一种思想,一种模式,一种套路,一种解决问题的高效策略。
有说的不正确或者不准确的地方欢迎留言指正
有什么有趣的写作技巧或者想法欢迎大家给我留言,大家的帮助是我写下去最有效的动力
![7643202-cac0195d49f25849.JPEG](https://i-blog.csdnimg.cn/blog_migrate/b2568e5364d5d48fecde27979b6872de.jpeg)
![7643202-4fe26c965ac0391a.jpg](https://i-blog.csdnimg.cn/blog_migrate/c85ce8a06c7492b3d6dce5ff6731acf0.jpeg)
请问,大象装冰箱要几步???XD~~~
当然是3步啦!相信这是不少同学的第一反应,但是这种用程序表示大家会怎么写呢?当然有人会这么写,写一个大象装冰箱的类,在一个函数里面写上3步所有的过程,又或者把每一步写成一个函数,然后分别调用第一步函数、第二部函数和第三部函数~
上面所说的不失为一个解决方案,但是如果我们前期的需求打开冰箱的方式很多呢?装大象怎么装?分块?缩小?几个人装?等等一些列问题都无法确定的情况下怎么办呢,总不能都用if-else这种搞定吧。根据开闭原则我们知道,改变原有的类是很危险的~其实在设计模式中有一种设计模式,用在这种情况下非常合适,那就是模板方法模式
模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
首先我创建一个抽象基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Custom.Log;
public abstract class PutSomething
{
protected void LogLine()
{
this.Log(new string('*', 20));
}
public virtual void BeginPut()
{
StepOne();
StepTwo();
StepThree();
LogLine();
}
public abstract void StepOne();
public abstract void StepTwo();
public abstract void StepThree();
}
具体装什么,怎么装由不同的子类来实现
public class PutElephant : PutSomething
{
public override void StepOne()
{
this.Log($"打开冰箱门{nameof(PutElephant)}");
}
public override void StepTwo()
{
this.Log($"把大象推进去{nameof(PutElephant)}");
}
public override void StepThree()
{
this.Log($"$把冰箱门关上{nameof(PutElephant)}");
}
}
调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TemplateMethodComponent : MonoBehaviour
{
void Start()
{
PutSomething putSomething = new PutElephant();
putSomething.BeginPut();
}
}
打印结果
![7643202-2fdf288f9b39557a.png](https://i-blog.csdnimg.cn/blog_migrate/4fbb9623f04f6e703416d9cdacb6c404.png)
我们的模板方法模式这就完成了,大家是不是感觉很简单呢?让执行依赖抽象,把具体的实现细节转移到不同的子类里去。如果说模板方法仅仅这点优势就完了吗?当然不是,看下面的示例
public class PutElephantEX : PutSomething
{
public override void BeginPut()
{
StepTwo();
StepThree();
LogLine();
}
public override void StepOne()
{
this.Log($"打开冰箱门{nameof(PutElephantEX)}");
}
public override void StepTwo()
{
this.Log($"把大象推进去{nameof(PutElephantEX)}");
}
public override void StepThree()
{
this.Log($"把冰箱门关上{nameof(PutElephantEX)}");
}
}
![7643202-3716929de59c3ac5.png](https://i-blog.csdnimg.cn/blog_migrate/94528c58471032e8b6d211bc9ae6faef.png)
因为下层的PutSomething中的有virtual函数,如果上层实现细节的时候与下层的“骨架”有冲突,我们就可以重写他,完全不需要更改任何下层的东西。这种结构让我们装东西三步走变得无限可能~~~
调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TemplateMethodComponent : MonoBehaviour
{
void Start()
{
PutSomething putSomething = new PutElephant();
putSomething.BeginPut();
putSomething = new PutElephantEX();
putSomething.BeginPut();
}
}
打印信息
![7643202-2f1aecf9ba3ae4c4.png](https://i-blog.csdnimg.cn/blog_migrate/673a4c25bd3c36dcc6a9ed210cbc4fe3.png)
如果我们后期需求有不同的容器和不同需要装的物体,我们也可以把容器和需要装的物体抽象,调用的时候只需要传入对象的抽象即可,复用性也会大大的增加。缺点嘛就是代码要多些一点,这种零零碎碎的东西会很多。这样我们装东西就变成一个无限大的百宝箱,想怎么装就怎么装!不知道同学们对模板方式模式的要点有没有Get到呢?
![7643202-fc30dc4095b00430.png](https://i-blog.csdnimg.cn/blog_migrate/a21b1358aa04e854b58047e593afe681.png)