模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
/**
* 模版方法
*/
public class TemplateMethodDemo {
abstract class TemplateMethod{
//钩子的开关
boolean needBeforeDo = true;
/**
* 钩子
*/
abstract void beforeDo();
void start(){
System.out.println("开始工作...");
}
/**
* 期望子类实现的方法
*/
abstract void toDo();
void end(){
System.out.println("结束工作...");
}
/**
* 默认实现流程
*/
public final void methodDo(){
if (needBeforeDo) {
beforeDo();
}
this.start();
this.toDo();
this.end();
}
}
class Method extends TemplateMethod{
/**
* 通过构造方法 决定模板方法的钩子是否开启
* @param needBeforeDo
*/
public Method(boolean needBeforeDo) {
super.needBeforeDo = needBeforeDo;
}
/**
* 钩子
*/
@Override
void beforeDo() {
}
/**
* 具体实现的方法
*/
@Override
void toDo() {
}
}
}
总结
模板方法模式是将子类中不变的部分抽象到父类,可变的部分由子类去实现。
优点
封装不变公共代码,便于维护。可变部分的代码由子类自由决定,扩展性强。
缺点
每新增一个不同的实现都需要增加一个子类,可能导致类数量变多,增加系统复杂性。
外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
/**
* 外观模式
* 模拟计算机开机
*/
public class FacadeDemo {
class CPU{
public void startCPU(){
System.out.println("CPU started...");
}
}
class Disk{
public void startDisk(){
System.out.println("Disk started...");
}
}
class Memory{
public void startMemory(){
System.out.println("Memory started...");
}
}
/**
* 外观类
*/
class StartBtn{
public void start(){
FacadeDemo demo = new FacadeDemo();
demo.new CPU().startCPU();
demo.new Disk().startDisk();
demo.new Memory().startMemory();
}
}
public void test(){
FacadeDemo demo = new FacadeDemo();
//不使用外观模式 开机过程需要
demo.new CPU().startCPU();
demo.new Disk().startDisk();
demo.new Memory().startMemory();
//使用外观模式后 只需要
demo.new StartBtn().start();
}
}
外观模式不仅为我们提供了一个简单方便的接口,也让我们的系统和子系统解耦。
迪米特法则(最少知道原则)
迪米特法则是说每一个类都应该尽量的少知道别的类,外观模式就是迪米特法则的应用。原本我们需要知道许多的子系统或接口,用了外观类之后,我们仅仅需要知道外观类即可。
换句话说就是:知道的太多对你没好处。
迪米特法则是希望类之间减少耦合,类越独立越好。有句话叫牵一发而动全身,如果类之间关系太紧密,与之关联的类太多,一旦你修改该类,也会牵动许多与之关联的类。
总结
外观模式主要使用场景:
- 包装多个复杂的子系统,提供一个简单的接口
- 重新包装系统,隐藏不想暴露的接口
优点
将复杂的接口简单化,减少了客户端与接口之间的耦合,提高了安全性。
缺点
可能产生大量的中间类(外观类),一定程度上增加了系统的复杂度。