设计模式之行为型——访问者模式、中介者模式、解释器模式

→23种设计模式大纲

1)访问者模式

访问者模式:Visitor Pattern

在这里插入图片描述

访问者模式在行为型设计模式里面算的上是最复杂的,使用也较少,但在某些特定场合很有必要。

主要角色:

  • 抽象Element接口:定义一个能被 Visitor (访问者类) 访问的方法;
  • 具体Element角色:需要被增加和特殊处理的原始对象,有基本的属性,并且需要实现 accept方法,通常将自身this)传给 Visitor 类,让 visitor 类可以操控元素的所有属性,进行额外操作;
  • 抽象Visitor接口:定义访问所有element元素的visit方法;
  • 具体Visitor角色:实现 visit 方法,对传过来的特定元素进行特定处理;
  • 集合类:Object Structure ,持有所有Element元素的集合,提供统一的遍历方法

抽象元素和实现类

public interface Bill {

    void accept(AbstractVisitor visitor);
}

@Data
@NoArgsConstructor
@AllArgsConstructor
class BillA implements Bill {

    private String name;

    @Override
    public void accept(AbstractVisitor visitor) {
        //将自身作为入参,使得visitor可以访问元素的其他属性
        visitor.visit(this);
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
class BillB implements Bill {
    private String name;

    @Override
    public void accept(AbstractVisitor visitor) {
         //将自身作为入参,使得visitor可以访问元素的其他属性
        visitor.visit(this);
    }
}


抽象访问者和实现类

interface AbstractVisitor {

    void visit(BillA billA);

    void visit(BillB billB);
}

class VisitorA implements AbstractVisitor {

    @Override
    public void visit(BillA billA) {
        //获取元素的其他属性,做一些特别的处理
        System.out.println(billA.getName()+" va for ba");
    }

    @Override
    public void visit(BillB billB) {
        //获取元素的其他属性,做一些特别的处理
        System.out.println(billB.getName()+" va for bb");
    }
}

class VisitorB implements AbstractVisitor {

    @Override
    public void visit(BillA billA) {
        //获取元素的其他属性,做一些特别的处理
        System.out.println(billA.getName()+" vb for ba");
    }

    @Override
    public void visit(BillB billB) {
        //获取元素的其他属性,做一些特别的处理
        System.out.println(billB.getName()+" vb for bb");
    }
}

数据集合类 Object Structure

class Structure {
    private List<Bill> list;

    public void setList(List<Bill> list) {
        this.list = list;
    }

    public void view(AbstractVisitor abstractVisitor) {
        list.forEach(bill -> bill.accept(abstractVisitor));
    }
}
class Test {

    public static void main(String[] args) {
        Structure structure = new Structure();
        structure.setList(Arrays.asList(new BillA("A1"), new BillB("B1 "),new BillA("A2"),new BillB("B2")));
        structure.view(new VisitorA());
        System.out.println("-------------------");
        structure.view(new VisitorB());
    }
}
  1. 需要对元素进行多种不同类型的操作时可以使用访问者模式,避免污染元素本身的属性(避免在元素内部加很多其他的逻辑)
  2. 元素本身属性和结构较为稳定,经常需要基于此结构增加额外的处理逻辑

其他案例:

  • 如学生实体有年龄、身高、体重、成绩、班级等属性,
  • 家庭老师需要根据学生的成绩来制定学习内容;体育老师需要根据学生的身体素质制定合适的训练计划,
  • 学生还分为高中生、初中生,各个老师对应的处理逻辑也不一样。

此时就可以使用访问者模式,学生除本身的基本属性外不需要添加额外的逻辑(体育老师,家庭老师等等对课程安排的处理)

再比如:员工分为正式工、实习生、兼职工、外包等等类型,财务发工资的时候有不同的处理。

2)中介者模式

中介者模式:Mediator Pattern

在这里插入图片描述

主要角色:

  • 抽象中介者:Mediator,定义基本的业务方法
  • 实现类中介者:Concrete Mediator,持有被调停者引用
  • 抽象被调停者:定义基本的业务方法,不一定有接口
  • 实现类被调停者:业务类
@AllArgsConstructor
public abstract class Colleague {
    protected Mediator mediator;
    public abstract void sendMsg(String msg);
    public abstract void notifyMsg(String msg);
}

class ConcreteColleague1 extends Colleague {

    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
        mediator.registerColleague(this);
    }

    @Override
    public void sendMsg(String msg) {
        mediator.send(msg, this);
    }

    @Override
    public void notifyMsg(String msg) {
        System.out.println("同事1获得消息 " + msg);
    }

}

class ConcreteColleague2 extends Colleague {

    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
        mediator.registerColleague(this);
    }


    @Override
    public void sendMsg(String msg) {
        mediator.send(msg, this);
    }

    @Override
    public void notifyMsg(String msg) {
        System.out.println("同事2获得消息 " + msg);
    }
}

interface Mediator {
    void send(String message, Colleague colleague);
    void registerColleague(Colleague colleague);
}

@Setter
class ConcreteMediator implements Mediator {
    ConcreteColleague1 concreteColleague1;
    ConcreteColleague2 concreteColleague2;
    @Override
    public void registerColleague(Colleague colleague){
        if(colleague instanceof  ConcreteColleague1){
            concreteColleague1= (ConcreteColleague1) colleague;
        }
        if(colleague instanceof  ConcreteColleague2){
            concreteColleague2= (ConcreteColleague2) colleague;
        }
    }
    @Override
    public void send(String message, Colleague colleague) {
        if (colleague == concreteColleague1) {
            concreteColleague1.notifyMsg(message);
        }

        if (colleague == concreteColleague2) {
            concreteColleague2.notifyMsg(message);
        }
    }
}

class Test {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();
        ConcreteColleague1 c1 = new ConcreteColleague1(mediator);
        ConcreteColleague2 c2 = new ConcreteColleague2(mediator);
        c1.sendMsg("asd");
        c2.sendMsg("nini");
    }
}

中介者模式旨在处理类于类之间的依赖关系,避免两个类直接关联。而是添加一个中介者用来处理两个类。

但其实类于类之间的依赖关系并不复杂时,并不需要使用中介者模式。反而会增加复杂度。

避免过于滥用中介者模式。

3)解释器模式

解释器模式:Interpreter Pattern

在这里插入图片描述

主要角色:

上下文:Context,存储所有的表达式

终结表达式:实现设计中的解释作用,在本例中为取值

非终结表达式: 实现设计中的运算左右,在本例中为运算规则

public interface Expression {
    int interpreter(Context context);
}

abstract class NonTerminalExpression implements Expression {
    Expression e1, e2;

    public NonTerminalExpression(Expression e1, Expression e2) {

        this.e1 = e1;
        this.e2 = e2;
    }
}

class MinusOperation extends NonTerminalExpression {

    public MinusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }

    @Override
    public int interpreter(Context context) {
        return this.e1.interpreter(context) - this.e2.interpreter(context);
    }
}

class PlusOperation extends NonTerminalExpression {
    public PlusOperation(Expression e1, Expression e2) {
        super(e1, e2);
    }

    @Override
    public int interpreter(Context context) {
        return this.e1.interpreter(context) + this.e2.interpreter(context);
    }
}

//终结表达式
class TerminalExpression implements Expression {

    String variable;

    public TerminalExpression(String variable) {

        this.variable = variable;
    }

    @Override
    public int interpreter(Context context) {
        //终结表达式的解释左右,此处终结表达式调用lookup,为从Context中取值
        return context.lookup(this);
    }
}

class Context {
    private Map<Expression, Integer> map = new HashMap<>();

    public void add(Expression s, Integer value) {
        map.put(s, value);
    }

    public int lookup(Expression s) {
        return map.get(s);
    }
}

class Test {
    public static void main(String[] args) {

        Context context = new Context();
        //定义基本值
        TerminalExpression terminalA = new TerminalExpression("a");
        TerminalExpression terminalB = new TerminalExpression("b");
        TerminalExpression terminalC = new TerminalExpression("c");
        context.add(terminalA, 4);
        context.add(terminalB, 8);
        context.add(terminalC, 2);
		
        //定义规则
        int result = new MinusOperation(
                         new PlusOperation(terminalA, terminalB), terminalC
           ).interpreter(context);
        System.out.println(result);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值