GOF 23设计模式之(行为型模式二)

北城以北 提交于 2020-01-07 12:41:54

目录

1.中介者模式

2.迭代器模式

3.访问者模式

4.备忘录模式

5.解析器模式

 

 

一、中介者模式(Mediator)

  定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,可以独立地改变他们之间的交互。又叫调停模式,是迪米特法则的典型应用。

  

  核心角色:

  (1)抽象中介者角色(Mediator):提供同事对象注册与转发同事对象信息的抽象方法。

  (2)具体中介者角色(Concrete Mediator):实现中介者接口,定义一个List来管理同事对象,协调各个同事角色之间的交互关系,因此依赖于同事角色。

  (3)抽象同事类角色(Colleague):定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。

  (4)具体同事类角色(Concrete Colleague):抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

 

  优点:

  (1)降低对象之间的耦合性,使得对象易于独立地被复用。

  (2)将对象间的一对多关联,转变为一对一的关联,提高系统的灵活性。

  

  缺点:

  (1)当同事类太多,中介者的职责将很大,会变得复杂而庞大,系统难于维护。

 

  

 

public class textMediator {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Mediator md = new ConcreteMediator();
        
        Colleague c1 = new ConcreteColleagueA();
        Colleague c2 = new ConcreteColleagueB();
        
        md.register(c1);
        md.register(c2);
        c1.send();
        
        System.out.println("----------");
        c2.send();
        
        
    } 
}

//抽象中介者 
abstract class Mediator{
    
    public abstract void register(Colleague colleague);
    public abstract void relay(Colleague cl);//转发
}

//具体中介者
class ConcreteMediator extends Mediator{

    private List<Colleague> colleagues = new ArrayList<Colleague>();
    
    @Override
    public void register(Colleague colleague) {
        
        if(!colleagues.contains(colleague)) {
            colleagues.add(colleague);
            colleague.setMediator(this);
        }
    }

    @Override
    public void relay(Colleague cl) {
        
        for (Colleague ob : colleagues) {
            if(!ob.equals(cl)) {
                ((Colleague)ob).recevie();
            }
        }
    }
}

//抽象同事类
abstract class Colleague{
    
    protected Mediator mediator;
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
    
    public abstract void recevie();
    public abstract void send();
}

//具体同事类A
class ConcreteColleagueA extends Colleague{

    @Override
    public void recevie() {
        System.out.println("具体同事类A收到请求");
    }

    @Override
    public void send() {
        System.out.println("具体同事类A发出请求");
        mediator.relay(this);//请中介者转发
    }
}

//具体同事类B 
class ConcreteColleagueB extends Colleague{

    @Override
    public void recevie() {
        System.out.println("具体同事类B收到请求");
    }

    @Override
    public void send() {
        System.out.println("具体同事类B发出请求");
        mediator.relay(this); //请中介者转发
    }
}
View Code

返回顶部

 

二、迭代器模式(Iterator)

  提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。就是在不透露聚合对象内部的结构的情况下,让外部代码透明地访问聚合的内部数据。

 

  核心角色:

  (1)抽象聚合角色(Aggregate):定义存储、添加、删除聚合对象以及创建迭代器对象的接口。

  (2)具体聚合角色(Concrete Aggregate):实现抽象聚合类,返回一个具体迭代器的实例。

  (3)抽象迭代器角色(Iterator):定义访问和遍历聚合元素的接口,通常包含hasNext()、first()、next()等方法。

  (4)具体迭代器角色(Concrete Iterator):实现抽象迭代器接口中定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

 

  优点:

  (1)访问一个聚合对象的内容,无需暴露它的内部表示。

  (2)遍历任务交给迭代器完成,简化了聚合类。

  (3)支持不同方式遍历一个聚合,并且可以自定义迭代器的子类来支持新的遍历。

  (4)增加新的聚合和迭代器类不需要修改原有代码。

  (5)封装性良好,为遍历不同的聚合结构提供一个统一的接口。

 

  缺点:

  (1)增加类的的个数,在一定程度上增加了系统的复杂性。

 

  

public class textAggregate {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
    
        Aggregate ag = new ConcreteAggregate();//所有内聚对象
        ag.add("第一个内聚");
        ag.add("第二个内聚");
        ag.add("第三个内聚");
        
        Iterator iterator = ag.getIterator();//获取内聚对象
        
        while(iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next.toString());
        }
    } 
}

//抽象聚合
interface Aggregate{
    
    public void add(Object obj);
    public void remove(Object obj);
    public Iterator getIterator();
    
}

//具体聚合
class ConcreteAggregate implements Aggregate{

    private List<Object> list = new ArrayList<Object>();
    
    @Override
    public void add(Object obj) {
        list.add(obj);
    }

    @Override
    public void remove(Object obj) {
        list.remove(obj);
    }

    @Override
    public Iterator getIterator() {
        
        return (new ConcreteIterator(list));
    }
}

//抽象迭代器
interface Iterator{
    
    Object frist();
    Object next();
    boolean hasNext();
}

//具体迭代器
class ConcreteIterator implements Iterator{
    
    private List<Object> list = null;
    private int index = 0;
    
    public ConcreteIterator(List<Object> list) {
        this.list = list;
    }

    @Override
    public Object frist() {
        
        index = 0;
        Object obj = list.get(index);
        
        return obj;
    }

    @Override
    public Object next() {
    
        Object obj = null;
        
        if(this.hasNext()) {
            obj = list.get(index++);
        }
        
        return obj;
    }

    @Override
    public boolean hasNext() {
        
        if(index >= list.size()) {
            return false;
        }else {
            return true;
        }
        
    }
}
View Code

返回顶部

 

三、访问者模式(Visitor)

  用于某种数据结构中的各个元素的操作分离出来封装成独立的类,使不改变数据结构的前提下可以添加新的操作,为数据结构中每个元素提供多种访问方式。

 

  核心角色:

  (1)抽象访问者角色(Visitor):定义一个访问具体元素的接口。为每个具体元素类对应一个访问操作visit(),该操作中的类型标识了被访问的具体元素。

  (2)具体访问者角色(Concrete Visitor):实现抽象访问者角色中声明的访问操作,确定访问者访问一个元素时该做什么。

  (3)抽象元素角色(Element):声明一个包含接受操作accept()的接口,被接受的访问者对象作为accept()方法的参数。

  (4)具体元素角色(Concrete Element):实现抽象元素角色提供的accept()操作,其方法体通常都是visitor.visit(this),另外具体元素中可能还包含本身业务逻辑的相关操作。

  (5)对象结构角色(Object Structure):一个包含元素角色的容器,提供让访问者对象遍历容器中所有元素的方法,通常有List、Set、Map等聚合实现。

 

  优点:

  (1)扩展性能好。不修改对象结构的元素情况下,添加新的功能。

  (2)复用性好。可以通过访问者定义整个对象结构通用的功能。

  (3)灵活性好。将数据结构与作用域结构上的操作解耦,使操作可以相对自由地演化而不影响系统的数据结构。

  (4)符合单一职责原则。把相关的行为封装在一起,构成一个访问者,使每个访问者功能都比较单一

 

  缺点:

  (1)增加新的元素类很困难。每增加一个新的元素,都要在每一个具体访问者类中增加相应的具体操作。违背了开闭原则。

  (2)破坏封装。具体元素对访问者公布细节。

  (3)违反了依赖倒置原则。依赖具体类,而没有依赖抽象类。

 

  

public class textVisitor {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
    
        
        ObjectStructure os = new ObjectStructure();
        
         os.add(new ConcreteElementA());
         os.add(new ConcreteElementB());
         
         Visitor visitor = new ConcreteVisitorA();
         
         os.accpet(visitor);
         
         System.out.println("---------");
         
         os.accpet(visitor);
    } 
}

//抽象访问者
interface Visitor{
    void visit(ConcreteElementA element);
    void visit(ConcreteElementB element);
}

//具体访问者A
class ConcreteVisitorA implements Visitor{

    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者A访问-->"+element.operationA());
    }

    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者A访问-->"+element.operationB());
    }
    
}

//具体访问者B
class ConcreteVisitorB implements Visitor{

    @Override
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者B访问-->"+element.operationA());
    }

    @Override
    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者B访问-->"+element.operationB());
    }
    
}

//抽象元素类
interface Element{
    
    void accept(Visitor visitor);
}

//具体元素A
class ConcreteElementA implements Element{

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    
    public String operationA() {
        return "具体元素A的操作";
    }
}

//具体元素B
class ConcreteElementB implements Element{

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    
    public String operationB() {
        return "具体元素B的操作";
    }
}


//对象结构角色
class ObjectStructure{
    
    private List<Element> list = new ArrayList<Element>();
    
    public void accpet(Visitor visitor) {
        
        Iterator<Element> i = list.iterator();
        
        while(i.hasNext()) {
            ((Element) i.next()).accept(visitor);
        }
    }
    
    public void add(Element element) {
        list.add(element);
    }
    
    public void remove(Element element) {
        list.remove(element);
    }
}
View Code

返回顶部

 

四、备忘录模式(Memento)

   在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便将该对象恢复到原来保存的状态。又叫快照模式。

 

  核心角色: 

  (1)发起人角色(Originator):记录当前时刻内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,可以访问备忘录里所有的信息。  

  (2)备忘录角色(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。

  (3)管理者角色(Caretaker):对备忘录进行管理,提供保存于获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

 

  优点:

  (1)提供一种可以恢复状态的封装。可以恢复到某个历史操作

  (2)实现了内部状态的封装。除了创建的发起人之外,其他对象不能够访问。

  (3)简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,符合单一职责原则。

 

  缺点:

  (1)资源消耗大。如果保存的内部状态信息过多或者特别繁杂,将会导致占用比较大的内存资源。

 

  

public class textMemento {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
    
        
        Originator or = new Originator();
        Caretaker cr = new Caretaker();
        or.setState("s0");
        System.out.println("初始状态"+or.getState());
        
        cr.setMemento(or.createMemento()); //保存状态
        
        or.setState("s1");//更新状态
        System.out.println("更新状态"+or.getState());
        
        or.restoreMemento(cr.getMemento());//恢复
        System.out.println("恢复状态"+or.getState());
        
    } 
}


//备忘录
class Memento{
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

//发起人
class Originator{
    private String state;
    
    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    
    public Memento createMemento() {
        return new Memento(state);
    }
    
    public void restoreMemento(Memento m) {
        this.setState(m.getState());
    }
}

//管理者
class Caretaker{
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}
View Code

返回顶部

 

 五、解析器模式(Interpreter)

   给对象一个语言,并定义该语言的文法表示,再设计一个解析器来解析语言中的句子。就是用编译语言的方式来分析应用中的实例。实现了文法表达式处理的接口,该接口解析一个特定的上下文。

 

  核心角色:

  (1)抽象表达式角色(Abstract Expression):定义解析器的接口,约定解析器的解析操作,主要包含解析方法interpret();

  (2)终结符表达式角色(Terminal Expression):抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。

  (3)非终结符表达式角色(Nonterminal Expression):也是抽象表达式的子类,用来实现文法中与非终结符相关的操作。

  (4)环境角色(Context):包含各个解析器需要的数据或者是公共的功能,一般用来传递被所有解析器共享的数据,后面的解析器可以从这里获取这些值。

  (5)客户端(Client):将需要分析的句子或表达式转换成使用解析器对象描述的抽象语法树,然后调用解析器的解析方法,当然也可以通过环境角色简接访问解析器的解析方法。

 

  优点:

  (1)扩展性好。通过继承等机制来改变或扩展文法。  

  (2)容易实现。在语法树中的每个表达式节点类都相似的,所以实现其文法容易。

  

  缺点:

  (1)执行效率低。使用大量的循环和递归调用。

  (2)会引起类膨胀。每条规则至少需要定义一个类,包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理和维护。

  (3)可应用场景少。

 

  

//抽象表达式类
interface AbstractExpression{
    
    public Object interpret(String info);//解析方法
}

//终结符表达式
class TerminalExpression implements AbstractExpression{

    @Override
    public Object interpret(String info) {
        
        //对终结符表达式处理
        
        return null;
    }
}

//非终结符表达式
class NonterminalExpression implements AbstractExpression{

    @Override
    public Object interpret(String info) {
    
        //对非终结符表达式处理
        
        return null;
    }
}

//环境类
class Context{
    
    private AbstractExpression exp;
    
    public Context() { //数据初始化
        
    }
    
    public void operation(String info) {
        //调用相关表达式类的解析方法
        
    }
}
View Code

返回顶部

 

     

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!