前言
这篇博客继续学习解释器、模板、观察者三种模式。
解释器模式
解释器是一种用的比较少的行为模式,其提供了一种解释语言的语法,或者表达式的方式。该模式定义了一个表达式的接口。
使用场景
使用场景最为频繁的就是手机号码验证
移动:134、135、136、137、138、139、150、151、157(TD)、158、159、187、188
联通:130、131、132、152、155、156、185、186
电信:133、153、180、189、(1349卫通)
其实上面的号码验证需要使用正则表达式”^((13[0-9])|(15[^4,\D])|(18[0,5-9]))\d{8}$”,但是计算机并不认识正则表达式,这个时候就需要有一个正则表达式的解释器来解释此表达式。
重点:
必须有一个抽象接口以及构建语法树
实现如下:
这里以处理一个四则运算为例:3 * 2 * 4 / 6 % 5,计算机是不知道如何去运算的,所以就需要利用解释器来进行先后顺序的运算。
抽象表达式:Node.Java
public interface Node
{
public int interpret();
}
非终结表达式:ValueNode.java。主要用解释该表达式的值
public class ValueNode implements Node
{
private int value;
public ValueNode(int value)
{
this.value=value;
}
public int interpret()
{
return this.value;
}
}
终结表达式抽象类,由于该终结表达式需要解释多个运算符号,同时用来构建抽象语法树:
public abstract class SymbolNode implements Node
{
protected Node left;
protected Node right;
public SymbolNode(Node left,Node right)
{
this.left=left;
this.right=right;
}
}
MulNode.java
public class MulNode extends SymbolNode
{
public MulNode(Node left,Node right)
{
super(left,right);
}
public int interpret()
{
return left.interpret() * right.interpret();
}
}
ModNode.java
public class ModNode extends SymbolNode{
public ModNode(Node left,Node right){
super(left,right);
}
public int interpret(){
return super.left.interpret() % super.right.interpret();
}
}
DivNode.java
public class DivNode extends SymbolNode{
public DivNode(Node left,Node right){
super(left,right);
}
public int interpret(){
return super.left.interpret() / super.right.interpret();
}
}
Calculator.java
public class Calculator{
private String statement;
private Node node;
public void build(String statement){
Node left=null,right=null;
Stack stack=new Stack();
String[] statementArr=statement.split(" ");
for(int i=0;i<statementArr.length;i++){
if(statementArr[i].equalsIgnoreCase("*")){
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new MulNode(left,right));
}
else if(statementArr[i].equalsIgnoreCase("/")){
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new DivNode(left,right));
}
else if(statementArr[i].equalsIgnoreCase("%")){
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new ModNode(left,right));
}
else{
stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
}
}
this.node=(Node)stack.pop();
}
public int compute()
return node.interpret();
}
}
客户端:Client.java
public class Client{
public static void main(String args[]){
String statement = "3 * 2 * 4 / 6 % 5";
Calculator calculator = new Calculator();
calculator.build(statement);
int result = calculator.compute();
System.out.println(statement + " = " + result);
}
}
优缺点:
优点
1、 可扩展性比较好,灵活。
2、 增加了新的解释表达式的方式。
3、 易于实现文法。
缺点
1、 执行效率比较低,可利用场景比较少。
2、 对于复杂的文法比较难维护。
模板方法模式
定义
定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类不改变算法的结构即可重复定义算法的某些特点步骤.
角色
AbstractClass抽象类,定义算法结构,还可以提供通用实现
ConcreteClass具体实现类 选择性的重定义算法中某些特定步骤
实现如下:
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
public final void play()
{
System.out.println("游戏开机");
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
System.out.println("游戏关机");
}
}
public class LoLGame extends Game{
@Override
void initialize() {
System.out.println("初始化英雄联盟");
}
@Override
void startPlay() {
System.out.println("攻入敌方战场");
}
@Override
void endPlay() {
System.out.println("每打赢,失败,退出游戏");
}
}
public class Client {
public static void main(String[] args) {
Game game=new LoLGame();
game.play();
}
}
模板方法模式是使用最简单也是使用最频繁的设计模式。
观察者设计模式
定义:
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
角色:
抽象主题(Subject)角色
抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
具体主题(ConcreteSubject)角色
将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
抽象观察者(Observer)角色
为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
具体观察者(ConcreteObserver)角色
存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
实现如下:
/**
* 抽象被观察者
* @author Administrator
*
*/
public class AbstractSubject {
/**
* 保存注册观察者对象
*/
private List<Observer> list=new ArrayList<>();
/**
* 添加观察者
* @param observer
*/
public void attach(Observer observer)
{
list.add(observer);
}
/**
* 删除观察者
* @param observer
*/
public void detach(Observer observer)
{
list.remove(observer);
}
/**
* 更新所有注册的观察者
* @param content
*/
public void notifyObservers(String content)
{
for(Observer observer:list)
{
observer.update(content);
}
}
}
public interface Observer {
/**
* 更新接口
* @param state
*/
public void update(String state);
}
public class ConcreteObserver implements Observer{
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String content) {
System.out.println(name+": "+content);
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject subject=new ConcreteSubject();
Observer observer1=new ConcreteObserver("观察者一");
Observer observer2=new ConcreteObserver("观察者二");
Observer observer3=new ConcreteObserver("观察者三");
subject.attach(observer1);
subject.attach(observer2);
subject.attach(observer3);
subject.notifyObservers("被观察者 发生了变化");
}
}
观察者模式也是使用比较广泛的设计模式之一,安卓中的setOnClickListener也是观察者模式的一种,只不过是一种单向的观察者模式。