xiaobenchi

导航

设计模式之行为型3

设计模式之行为型3

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1. 迭代器模式

迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。核心:为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。

  • 迭代模式结构图

    迭代模式

  • 迭代器实现

    • Iterator迭代器抽象类

      abstract class Iterator{
          //用于定义得到开始对象、下一个对象、判断是否到结尾、当前对象等抽象方法,
          //统一接口
          public abstract Object first();
          public abstract Onject next();
          public abstract boolean isDone();
          public abstract Onject currentItem()
      }
      
    • Aggregate聚集抽象类

      abstract class Aggregate{
          //创建迭代器
          public abstract Iterator createIterator();
      }
      
    • ConcreteIterator具体迭代类,继承Iterator

      class ConcreteIterator extends Iterator{
          //定义具体聚集对象
          private ConcreteAggregate aggregate;
          private int current = 0;
          
          //初始化时将具体的聚集对象传入
          public ConcreteIterator(ConcreteAggregate aggregate){
              this.aggregate = aggregate;
          }
          
          //得到聚集的第一个对象
         @override
          public Object first(){
              return aggregate[0];
          }
          //得到聚集的下一个对象
          @override
          public Object next(){
              Object ret = null;
              current++;
              if(current < aggregate.count()){
                  ret = aggregate[current];
              }
              return ret;
          }
          
          //判断当前是否遍历到结尾
          @override
          public boolean isDone(){
              return current >= aggregate.count ? true:false;
          }
          
          //返回当前的聚集对象
          @override
          public Object currentItem(){
              return aggregate[current];
          }
      }
      
    • ConcreteAggregate 具体聚集类,继承Aggregate

      class ConcreteAggregate extend Aggregate{
          private List<Object> items = new ArrayList<>();
          private int index;
          @override
          public Iterator createIterator(){
              return new ConcreteIterator(this);
          }
          
          //返回聚集个数
          public int count(){
              return item.size();
          }
          
          //声明一个索引
          public void setIndex(int index){
              this.index = index;
          }
          public int getIndex(){
              return index;
          }
      }
      
    • 客户端代码

      static void main(String[] args){
          ConcreteAggregate a = new ConcreteAggregate();
          a[0] = "大鸟";
          a[1] = "小菜";
          a[2] = "老外";
          a[3] = "小偷";
          
          Iterator i = new ConcreteIterator(a);
          Object item = i.first();
          while(!i.isDone){
              System.out.println("请买票"+i.currentItem());
              i.next();
          }
      }
      
  • 迭代器模式应用实例

    编写一个程序展示一个学校的院系结构

    • 类图

      image-20220730102411282

    • department系类

      //ϵ
      public class Department {
       
      	private String name;
      	private String desc;
      	public Department(String name, String desc) {
      		super();
      		this.name = name;
      		this.desc = desc;
      	}
      	public String getName() {
      		return name;
      	}
      	public void setName(String name) {
      		this.name = name;
      	}
      	public String getDesc() {
      		return desc;
      	}
      	public void setDesc(String desc) {
      		this.desc = desc;
      	}
      }
      
    • ComputerCollegeIterator,计算机学院迭代器类

      import java.util.Iterator;
       
       
      public class ComputerCollegeIterator implements Iterator {
       
      	//这里我们需要Department 是以怎样的方式存放=>数组
      	Department[] departments;
      	int position = 0; //遍历的位置
      	
      	public ComputerCollegeIterator(Department[] departments) {
      		this.departments = departments;
      	}
       
      	//判断是否还有下一个元素
      	@Override
      	public boolean hasNext() {
      		// TODO Auto-generated method stub
      		if(position >= departments.length || departments[position] == null) {
      			return false;
      		}else {
      		
      			return true;
      		}
      	}
       
      	@Override
      	public Object next() {
      		// TODO Auto-generated method stub
      		Department department = departments[position];
      		position += 1;
      		return department;
      	}
      	
      	//删除的方法,默认空实现
      	public void remove() {
      		
      	}
      }
      
    • InfoColleageIterator

      import java.util.Iterator;
      import java.util.List;
       
      public class InfoColleageIterator implements Iterator {
       
      	
      	List<Department> departmentList; // 信息工程学院是以List方式存放系
      	int index = -1;//索引
      	
       
      	public InfoColleageIterator(List<Department> departmentList) {
      		this.departmentList = departmentList;
      	}
       
      	//判断list中还有没有下一个元素
      	@Override
      	public boolean hasNext() {
      		// TODO Auto-generated method stub
      		if(index >= departmentList.size() - 1) {
      			return false;
      		} else {
      			index += 1;
      			return true;
      		}
      	}
       
      	@Override
      	public Object next() {
      		// TODO Auto-generated method stub
      		return departmentList.get(index);
      	}
      	
      	//空实现remove
      	public void remove() {
      		
      	} 
      }
      
    • College学校接口

      import java.util.Iterator;
       
      public interface College {
      	
      	public String getName();
      	
      	//增加系的方法
      	public void addDepartment(String name, String desc);
      	
      	//返回一个迭代器,遍历
      	public Iterator  createIterator();
      }
      
    • ComputerCollege类实现College接口

      import java.util.Iterator;
       
      public class ComputerCollege implements College {
       
      	Department[] departments;
      	int numOfDepartment = 0 ;// 保存当前数组的对象个数
      	
      	
      	public ComputerCollege() {
      		departments = new Department[5];
      		addDepartment("Java专业", " Java专业 ");
      		addDepartment("PHP专业", " PHP专业 ");
      		addDepartment("大数据专业", " 大数据专业 ");
      		
      	}
      	
      	
      	@Override
      	public String getName() {
      		// TODO Auto-generated method stub
      		return "计算机学院";
      	}
       
      	@Override
      	public void addDepartment(String name, String desc) {
      		// TODO Auto-generated method stub
      		Department department = new Department(name, desc);
      		departments[numOfDepartment] = department;
      		numOfDepartment += 1;
      	}
       
      	@Override
      	public Iterator createIterator() {
      		// TODO Auto-generated method stub
      		return new ComputerCollegeIterator(departments);
      	}
       
      }
      
    • InfoCollege实现College接口

      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.List;
       
      public class InfoCollege implements College {
       
      	List<Department> departmentList;
      	
      	
      	public InfoCollege() {
      		departmentList = new ArrayList<Department>();
      		addDepartment("信息安全专业", " 信息安全专业 ");
      		addDepartment("网络安全专业", " 网络安全专业 ");
      		addDepartment("服务器安全专业", " 服务器安全专业 ");
      	}
      	
      	@Override
      	public String getName() {
      		// TODO Auto-generated method stub
      		return "信息工程学院";
      	}
       
      	@Override
      	public void addDepartment(String name, String desc) {
      		// TODO Auto-generated method stub
      		Department department = new Department(name, desc);
      		departmentList.add(department);
      	}
       
      	@Override
      	public Iterator createIterator() {
      		// TODO Auto-generated method stub
      		return new InfoColleageIterator(departmentList);
      	}
      }
      
    • 输出

      import java.util.Iterator;
      import java.util.List;
       
      public class OutPutImpl {
      	
      	//学院集合
      	List<College> collegeList;
       
      	public OutPutImpl(List<College> collegeList) {
      		
      		this.collegeList = collegeList;
      	}
      	//遍历所有学院,然后调用printDepartment 输出各个学院的系
      	public void printCollege() {
      		
      		//从collegeList 取出所有学院, Java 中的 List 已经实现Iterator
      		Iterator<College> iterator = collegeList.iterator();
      		
      		while(iterator.hasNext()) {
      			//取出一个学院
      			College college = iterator.next();
      			System.out.println("=== "+college.getName() +"=====" );
      			printDepartment(college.createIterator()); //得到对应迭代器
      		}
      	}
      		
      	//输出学院输出系
      	public void printDepartment(Iterator iterator) {
      		while(iterator.hasNext()) {
      			Department d = (Department)iterator.next();
      			System.out.println(d.getName());
      		}
      	}	
      }
      
    • 客户端

      import java.util.ArrayList;
      import java.util.List;
       
      public class Client {
       
      	public static void main(String[] args) {
      		// TODO Auto-generated method stub
      		//创建学院
      		List<College> collegeList = new ArrayList<College>();
      		
      		ComputerCollege computerCollege = new ComputerCollege();
      		InfoCollege infoCollege = new InfoCollege();
      		
      		collegeList.add(computerCollege);
      		//collegeList.add(infoCollege);
      		
      		OutPutImpl outPutImpl = new OutPutImpl(collegeList);
      		outPutImpl.printCollege();
      	}
      
      }
      
  • 小结

    优点:

    1. 提供统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。
    2. 隐藏了聚合的内部结构
    3. 符合单一职责原则

    缺点:

    ​ 每个聚合对象都要一个迭代器,会生成多个迭代器,不好管理类。

2. 命令模式

命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

  • 命令模式结构图

    image-20220730105718254

  • 代码实现

    • Command类,用来声明执行操作的接口

      abstract class Command{
          protected Receiver receiver;
          
          public Command(Receiver receiver){
              this.receiver = receiver;
          }
          
          public abstract void execute();
      }
      
    • ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute。

      class ConcreteCommand extends Command{
          public ConcreteCommand(Receiver receiver) :super(receiver){}
          
          @override
          public void excute(){
              receiver.action();
          }
      }
      
    • Invoker类,要求该命令执行这个请求

      class Invoker{
          private Command command;
          
          public void setCommand(Command command){
              this.command = command;
          }
          
          public void executeCommand(){
              command.execute();
          }
      }
      
    • Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。

      class Receiver{
          public void action(){
              System.out.println("执行请求!");
          }
      }
      
    • 客户端

      static void main(String[] args){
          Receiver r = new Receiver();
          Command c = new ConcreteCommand(r);
          Invoker i = new Invoker();
          
          i.setCommand(c);
          i.ExecuteCommand();
      }
      
  • 小结

    命令模式的实现需要三部分:命令部分,通知部分,执行部分。

    命令部分对应不同的请求,执行部分对应不同的命令,通知部分对命令进行收集,排队,撤销,通知执行。

    命令模式是为了解决请求与执行部分的紧耦合,这不方便对请求做记录,排队,操作。

    命令模式的优点:1. 它能比较容易地设计一个命令队列;2. 在需要的情况下,可以较容易地将命令计入日志;3.允许接收请求的一方决定是否否决请求。

3. 责任链模式

责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

  • 责任链模式结构图

    image-20220730113329213

  • 代码实现

    • Handler类,定义一个处理请示的接口
    abstract class Handler{
        protected Handler successor;
        
        //设置继任者
        public void setSuccessor(Hander successor){
            this.successor = successor;
        }
        //处理请求的抽象方法
        public abstract void handleRequest(int request);
    }
    
    • ConcreteHandler类,具体处理类,处理它所负责的请求,可以访问它的后继者。

      //ConcreteHandler1,当请求数在0到10之间则有权处理,否则转移到下一位
      class ConcreteHandler1 extends Handler{
          @override 
          public void handleRequest(int request){
              if(request >= 0 && request < 10){
                  System.out.println("处理请求"+request);
              }else if(successor != null){
                  successor.handleRequest(request);
              }
          }
      }
      
      //ConcreteHandler2,当请求数在10到20之间则有权处理,否则转移到下一位
      class ConcreteHandler2 extends Handler{
          @override 
          public void handleRequest(int request){
              if(request >= 10 && request < 20){
                  System.out.println("处理请求"+request);
              }else if(successor != null){
                  successor.handleRequest(request);
              }
          }
      }
      
      //ConcreteHandler1,当请求数在0到10之间则有权处理,否则转移到下一位
      class ConcreteHandler3 extends Handler{
          @override 
          public void handleRequest(int request){
              if(request >= 20 && request < 30){
                  System.out.println("处理请求"+request);
              }else if(successor != null){
                  successor.handleRequest(request);
              }
          }
      }
      
    • 客户端代码

      static void main(String[] args){
          
          Handler h1 = new ConcreteHandler1();
          Handler h2 = new ConcreteHandler2();
          Handler h3 = new ConcreteHandler3();
          h1.setSuccessor(h2);
          h2.setSuccessor(h3);
          
          int[] requests = new int[]{2,5,3,4,7,14,25,4};
          for(int r : requests){
              h1.handleRequest(r);
          }
      }
      
  • 小结

    责任链模式使得当前执行者只需要知道它后继执行者即可。这种模式可避免大量的if-else判断,降低耦合,便于增删。

    但注意,若链中的各个执行者都不符合处理请求的条件,请求在链的末端一定要得到合适的处理。

posted on 2022-07-30 11:55  小迟在努力  阅读(35)  评论(0)    收藏  举报