我对设计模式的理解:

多数开发人员应该知道设计模式这个东西;部分人知道23种设计模式;少数人能够熟练使用设计模式,极少数人精通设计模式。

其实23种设模式,其实只是入门,这就相当于你学英语,学会了26个英文字母,才能开始学习单词。同样23种设计模式,只是字母表,想要到精通的层次,要能够灵活的使用设计模式,灵活的组合设计模式。

设计模式是我短期计划中的一部分,我的文章致力于最快最简单的掌握每一个设计模式。

我的设计模式相关的文章,都会在开篇使用一句话,来描述一个设计模式!

该模式设计关键点

使用抽象类,定义算法骨架,然后子类根据不同的场景来实现算法细节,达到解决不同问题的目的。

 

最大的好处

代码复用,代码结构清晰,符合开闭原则。

 

最大的缺点

类的个数膨胀。

 

UML图

快速学习设计模式-模板方法模式_设计模式

 该设计模式非常的简单,很容易掌握,也比较容易用到。

 定义一个抽象类(红色框),算法骨架方法,跟业务挂钩的抽象方法;

 然后由实现类,去实现跟自己业务相关的方法。

 

简单的使用

(一般大家对游戏比较有共鸣,那就举一个游戏的栗子吧):

 首先我定义了一个抽象类:AbstractGame

 该抽象类有五个方法,其中两个两个用final修饰的方法,其中一个是算法骨架,openGame(),该方法里边定义好了算法的执行流程,必须按照我预期的进行加载。我不想让子类擅自修改我们的算法骨架,所以我用final来修饰

 另外三个方法是抽象方法,分别是加载场景,和加载背景音乐的,和连接用户的方法。

abstract class AbstractGame {
/**
* 游戏算法骨架
*/
final void openGameTempl(){
//加载游戏场景
loadScene();
//加载背景音乐
loadBackgroundMusice();
//连线游戏用户
connectedUsers();
//开始游戏
begin();

}

/**
* 加载游戏场景
*/
abstract void loadScene();

/**
* 加载背景音乐
*/
abstract void loadBackgroundMusice();
/**
* 连线游戏用户
*/
abstract connectedUsers();
/**
* 开始游戏
*/
final void begin(){
System.out.println("欢迎来到召唤师峡谷");
}


}

 

 接着是实现类,三个方法是抽象方法,分别是加载场景,和加载背景音乐的,和连接用户的方法。如果想加载不同的游戏地图进来,则可以用子类去继承我们的抽象方法。如果想要是使用不同的连接用户的方法,使用语音,使用第三方聊天工具。

同样道理,如果是3v3 的游戏,则再定义一个子类来实现AbstractGame。 游戏的加载顺序是不变的,唯一边的就是我们的抽象方法。

class GameV5 extends AbstractGame{

/**
* 加载游戏场景
*/
@Override
void loadScene(){
System.out.println("加载5v5的游戏地图");
}

/**
* 加载背景音乐
*/
@Override
void loadBackgroundMusice(){
System.out.println("加载大乱斗的背景音乐");
}

/**
* 连线游戏用户
*/
@Override
void connectedUsers(){
System.out.println("使用QT语音进行用户的连接");
}


}

 

 想要开始一场5V5的游戏,则直接new一个对象即可。 

public class DoGame {
public static void main(String[] args) {
GameV5 gameV5 = new GameV5();
gameV5.openGameTempl();

}
}

 

 

灵活运用-模板方法下的钩子程序

其实这个是非常灵活的,还可以定义下边的四个方法为抽象方法。唯独定义全部的方法为抽象方法,不太合适。留出一个方法来定义算法骨架,这是模板方法的一个精髓点。

同事,我们还可以不把抽象类写太死,预留出来一些权利给子类。也就是通常说的钩子程序。

下边我对上边的案例做一点改变

abstract class AbstractGame {
/**
* 游戏算法骨架
*/
final void openGameTempl(){
//加载游戏场景
loadScene();
//加载背景音乐
loadBackgroundMusice();
//连线游戏用户
connectedUsers();
//开始游戏
begin();

}

/**
* 加载游戏场景
*/
abstract void loadScene();

/**
* 加载背景音乐
*/
abstract void loadBackgroundMusice();

/**
* 预留一个钩子,由子类决定是否加载
*/
if(isLoadSkin()){
//加载皮肤
loadSkin();
}

/*
* 是非加载皮肤
*/
protected boolean isLoadSkin(){
return false;
}

/**
* 连线游戏用户
*/
abstract connectedUsers();

/**
* 开始游戏
*/
final void begin(){
System.out.println("欢迎来到召唤师峡谷");
}


}

 

  在实现类中决定,是否加载皮肤。

class GameV5 extends AbstractGame{

/**
* 加载游戏场景
*/
@Override
void loadScene(){
System.out.println("加载5v5的游戏地图");
}

/**
* 加载背景音乐
*/
@Override
void loadBackgroundMusice(){
System.out.println("加载大乱斗的背景音乐");
}

/**
* 连线游戏用户
*/
@Override
void connectedUsers(){
System.out.println("使用QT语音进行用户的连接");
}

/*
* 是非加载皮肤
*/
@Override
protected boolean isLoadSkin(){
return true;
}


}

 

 想要开始一场5V5的游戏,则直接new一个对象即可。 

public class DoGame {
public static void main(String[] args) {
GameV5 gameV5 = new GameV5();
gameV5.openGameTempl();

}
}