吉林大学设计模式第四次作业(上)

找到这里的多半是我的学弟学妹了,怎么说呢,希望能帮到你们吧,也更希望我留在这里的思路和代码是你们的下限,设计模式真的很精妙,祝你们有所增益。


题目一

开发一个消防应急响应系统,火灾探测器(FireDetector)发现火灾异常后将自动传递信号给各种响应设备,例如警示灯(WarningLight)将闪烁(flicker())、报警器(Alarm)将发出警报(alarm())、安全逃生门(SecurityDoor)将自动开启(open())、隔离门(InsulatedDoor)将自动关闭(close())等,每一种响应设备的行为由专门的程序来控制。请写出你所选择的设计模式,画出类图,并给出核心代码。

由题意得这道题显然要使用观察者模式——当一个对象被修改时,则会自动通知依赖它的对象。

而观察者模式使用三个类:

  • Subject:抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
    • 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  • Observer:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
    - 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
  • Client

在这里插入图片描述
结合在这道题里:

  • Subject:抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法notifyObserver()。
    • 具体目标类(Concrete Subject):它实现抽象目标中的通知方法notifyObserver(),当发现火灾异常后将自动传递信号给各种响应设备(具体观察者),通知所有注册过的观察者对象。
      - 火灾探测器(FireDetector)
  • Observer:它是一个抽象类或接口,它包含了一个更新自己的抽象方法response(),当接到具体主题的更改通知时被调用。
    - 具体观察者(Concrete Observer)角色:
    - 警示灯(WarningLight):response(){//闪烁(flicker())}
    - 报警器(Alarm):response(){//发出警报(alarm())}
    - 安全逃生门(SecurityDoor):response(){//将自动开启(open())}
    - 隔离门(InsulatedDoor):response(){//将自动关闭(close())}
  • Client

代码:

import java.util.*;
public class Client {
    
    
    public static void main(String[] args) {
    
    
    
        //目标火灾探测器
        Subject subject = new FireDetector();
        //观察者
        Observer obs1 = new WarningLight();
        Observer obs2 = new Alarm();
        Observer obs3 = new SecurityDoor();
        Observer obs4 = new InsulatedDoor();
        
        subject.add(obs1);
        subject.add(obs2);
        subject.add(obs3);
        subject.add(obs4);
        subject.notifyObserver();
    }
}
//抽象目标
abstract class Subject {
    
    
    protected List<Observer> observers = new ArrayList<Observer>();
    //增加观察者方法
    public void add(Observer observer) {
    
    
        observers.add(observer);
    }
    //删除观察者方法
    public void remove(Observer observer) {
    
    
        observers.remove(observer);
    }
    public abstract void notifyObserver(); //通知观察者方法
}
//具体目标
class FireDetector extends Subject {
    
    
    public void notifyObserver() {
    
    
        System.out.println("注意注意!发生火灾异常!");
        System.out.println("--------------");
        for (Object obs : observers) {
    
    
            ((Observer) obs).response();
        }
    }
}
//抽象观察者
interface Observer {
    
    
    void response(); //反应
}
//具体观察者1
class WarningLight implements Observer {
    
    
    public void response() {
    
    
        System.out.println("警示灯开始闪烁!");
    }
}
//具体观察者1
class Alarm implements Observer {
    
    
    public void response() {
    
    
        System.out.println("报警器发出警报!");
    }
}

//具体观察者1
class SecurityDoor implements Observer {
    
    
    public void response() {
    
    
        System.out.println("安全逃生们已自动开启!");
    }
}

//具体观察者1
class InsulatedDoor implements Observer {
    
    
    public void response() {
    
    
        System.out.println("隔离门已自动关闭!");
    }
}

输出:
在这里插入图片描述


题目二

**某学校的差旅费报销制度规定,要根据不同的报销金额,由不同的领导审批,1万元以下科长审批,1万元至5万元之间处长审批,5万元至10万元之间副校长审批,10万元以上校长审批。最常用的编程思想是采用条件语句进行判断,但是随着差旅费报销制度的逐渐完善,可能需要判断的条件会越来越多,可能处理的逻辑也更加复杂,代码将变得难以维护。请选择恰当的设计模式解决该问题,画出类图,写出关键代码。
**

这道题是典型的责任链模式的应用。核心就是审批旅费报销这件事,经由不同的领导才能审批不同的额度。倘若员工必须根据费用的多少去找对应的领导那意味着他必须记住每个领导的信息,这是不现实的,实际运用中我们更希望我就找直系领导,他要是解决不了他就把这件事往上递交,而我本身只用跟一个领导交互。

职责链模式主要包含以下角色。

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。这道题里对应有四个具体处理者。
    - Chief:科长,处理1万元以下审批
    - Director:处长,处理1-5万元
    - VicePrincipal:副校长,处理5-10万元审批
    - Principal:校长,处理10万元以上审批
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

unl类图:

请添加图片描述

import java.io.IOException;
import java.util.Scanner;

public class Client {
    
    
    public static void main(String[] args) throws IOException {
    
    
        //组装责任链
        Handler handler1 = new Chief();
        Handler handler2 = new Director();
        Handler handler3 = new VicePrincipal();
        Handler handler4 = new Principal();
        handler1.setNext(handler2);
        handler2.setNext(handler3);
        handler3.setNext(handler4);

        //提交请求
    
        System.out.println("请选择要想申请的审批额度:\n——①1万元以下;\n——②1万元-5万元;\n——③5万元-10万元;\n——④10万元以上。");
        int in = System.in.read();  
        handler1.handleRequest(in-48);
    }
}
//抽象处理者角色
abstract class Handler {
    
    
    private Handler next;
    public void setNext(Handler next) {
    
    
        this.next = next;
    }
    public Handler getNext() {
    
    
        return next;
    }
    //处理请求的方法
    public abstract void handleRequest(int request);
}
//具体处理者角色1
class  Chief extends Handler {
    
    
    public void handleRequest(int request) {
    
    
        if (request == 1) {
    
    
            System.out.println("科长正在处理该请求!");
        } else {
    
    
            if (getNext() != null) {
    
    
                getNext().handleRequest(request);
            } else {
    
    
                System.out.println("没有人处理该请求!");
            }
        }
    }
}
//具体处理者角色2
class Director extends Handler {
    
    
    public void handleRequest(int request) {
    
    
        if (request == 2) {
    
    
            System.out.println("处长处理该请求!");
        } else {
    
    
            if (getNext() != null) {
    
    
                getNext().handleRequest(request);
            } else {
    
    
                System.out.println("没有人处理该请求!");
            }
        }
    }
}

//具体处理者角色3
class VicePrincipal extends Handler {
    
    
    public void handleRequest(int request) {
    
    
        if (request == 3) {
    
    
            System.out.println("副校长正在处理该请求!");
        } else {
    
    
            if (getNext() != null) {
    
    
                getNext().handleRequest(request);
            } else {
    
    
                System.out.println("没有人处理该请求!");
            }
        }
    }
}

//具体处理者角色2
class Principal extends Handler {
    
    
    public void handleRequest(int request) {
    
    
        if (request == 4) {
    
    
            System.out.println("校长正在处理该请求!");
        } else {
    
    
            if (getNext() != null) {
    
    
                getNext().handleRequest(request);
            } else {
    
    
                System.out.println("没有人处理该请求!");
            }
        }
    }
}

输出:
请添加图片描述

题目三

小王准备使用面向对象的方法设计一个快餐店的简单游戏,游戏中有顾客、服务员、菜品和厨师。每个顾客都有一个服务员帮助点菜,并且可以点多个菜;每道菜都由指定厨师制作,不同的菜可能由不同的厨师制作;顾客跟服务员点完菜后,服务员通知后厨做菜。请你针对上面的描述,帮助小王选择合适的设计模式进行设计。
1)简要说明你的设计思路和选择的模式。

老师给的标准答案:命令模式。……呜呜呜呜设计模式好难,稍微场景设置花一点完全设计不对呜呜呜呜

首先分析这道题,实质就是:服务员帮助顾客点菜,通知后厨做菜,不同菜可能由不同的厨师制作。
因此,其实可以分析出大概了,服务员特别像一个接口,与客户交互,然后将结果通知厨师,厨师根据菜品的不同分化给具体的人做。所以这道题我选择采用外观模式+职责链模式。

  • 外观模式:客户-服务员-得到点菜菜品
  • 职责链模式:菜品-具体厨师负责,相当于让相应的菜品自动匹配能做的厨师(不过下面解决中使用了哈希表就不用详写职责链了)

2)给出你设计的UML类图和实现代码。

请添加图片描述

import java.util.HashMap;


class Dish {
    
    
	public String name;		//菜肴的名称
	public Dish(String n) {
    
    	//初始化函数
		name=n;
	}
	public void cooked(){
    
    
	   System.out.println(name + "已做好!");
	}
}

class Chief {
    
    
	public String name;			//厨师的名称
	public List<dish>d = new ArrayLsit(); //每个厨师会做的菜
	public Chief(String n) {
    
    
		name  = n;
	}
	public void cook(String dishName) {
    
    
		System.out.println("正在做菜");
		d.get(dishNmae).cooked;
	}
}


class Waiter {
    
    
	private HashMap<String,Chief>map;			// Hash表用来保存每个厨师对应一个菜
	public Waiter() {
    
    
		map = new HashMap<String, Chief>();
		Chief chief_example = new Chief("example_chief");
		map.put("example", chief_example);
	}										//服务员掏出了菜单
	public void getOrder(Dish dish) {
    
    		// 服务员接收到指定的菜单找厨师做菜
		System.out.println(map.get(dish.name).name);//获取当前厨师名字
		map.get(dish.name).cook(dish.name); //调用该厨师做这道菜的方法
	}
}

class Customer {
    
    
	private Waiter waiter;
	//每个顾客都有一个服务员帮忙点菜
	public Customer() {
    
    
		waiter = new Waiter();
	}
	public void Order(Dish dish) {
    
    
		//点菜dish
		waiter.getOrder(dish);
	}
}

public class Client {
    
    
 
	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		Customer customer = new Customer();
		Dish dish = new Dish("example");
		customer.Order(dish);
	}
 

题目四

小明为某银行开发一个报警系统,该系统功能描述如下,请你帮助小明完成设计,给出设计模式的名称,画出类图,写出关键代码。
在这里插入图片描述

老师给的标准答案是:状态模式。emmmm这道题输的心服口服好吧,做的时候压根没学状态模式hhhh

我认为应该使用观察者模式
请添加图片描述

import java.util.*;
public class Client {
    
    
    public static void main(String[] args) {
    
    
    
    	AlarmSystem subject = new Treasury();
        //观察者
        Observer obs1 = new Alarm();
        Observer obs2 = new Telephone();
        
        subject.add(obs1);
        subject.add(obs2);
   
        subject.notifyObserver();
    }
}
//抽象目标
abstract class AlarmSystem {
    
    
    protected List<Observer> observers = new ArrayList<Observer>();
    //增加观察者方法
    public void add(Observer observer) {
    
    
        observers.add(observer);
    }
    //删除观察者方法
    public void remove(Observer observer) {
    
    
        observers.remove(observer);
    }
    public abstract void notifyObserver(); //通知观察者方法
}
//具体目标
class Treasury extends AlarmSystem {
    
    
    public void notifyObserver() {
    
    
        System.out.println("金库启动:");
        System.out.println("--------------");
        if(时间位于900~1659) {
    
    
            for (Object obs : observers) {
    
    
            ((Observer) obs).responseDay();
             }
        }else(时间位于000~8591700~2359) 
        {
    
    
        	for (Object obs : observers) {
    
    
            ((Observer) obs).responseNight();
        }
        	
        }
    }
}
//抽象观察者
interface Observer {
    
    
    void responseDay(); //白天反应
    void responseNight();//夜晚反应
}

class Alarm implements Observer {
    
    
    public void responseDay() {
    
    
        System.out.println("警铃正在调用。");
        System.out.println("向警报中心发送紧急事态通知!");
    }
    public void responseNight() {
    
    
        System.out.println("警铃正在调用。");
        System.out.println("向警报中心发送紧急事态通知!");
    }
}

class Telephone implements Observer {
    
    
    public void responseDay() {
    
    
    	System.out.println("电话正在调用。");
        System.out.println("正在呼叫警报中心");
    }
    public void responseNight() {
    
    
    	System.out.println("夜间留言电话正在调用。");
        System.out.println("正在呼叫警报中心的留言电话");
    }
}

题目五

** 小明正在开发一个病房呼叫应答仿真系统。系统中每个病房配备一个呼叫按钮和一个呼叫显示应答器,疗区大厅配备一个显示应答器和一个语音播报器。假设,按下001号病房的呼叫按钮后,那么,所有的呼叫显示应答器都会显示发出呼叫的病房号001,大厅同时语音播报该病房号001。当医护人员按下任意一处的呼叫显示应答器的应答按钮后,所有呼叫显示应答器停止显示该房间号,大厅也停止语音播报。请用恰当的设计模式实现该系统,画出类图,给出核心代码。**

已经麻木了,老师给的标准答案是:中介者模式。想一想也符合,原先的场景里病人、呼叫应答器、显示应答器、语音播报器、医护人员相互杂糅,有个中介者类把多对多关系变成一对一好像蛮不错的。但其实中介者模式和观察者模式都是行为型模式,核心是相似的,所以自己开始弄错了。

我觉得要使用观察者模式和单例模式

类图:
请添加图片描述

import java.util.ArrayList;
import java.util.List;
class Asking{
    
    
	public String name;
	public Asking(String name) {
    
    
		this.name=name;
	}
	public void show() {
    
    
		System.out.println(name);
	}
	public void back() {
    
    
		//撤回显示
	}
}

class Button{
    
    
	public String name;
	Asking a = null;
	public static List<Asking> ask = new ArrayList();
	public Button(String name) {
    
    
		this.name=name;
		a = new Asking(name);
		ask.add(a);
	}
	public void getButton() {
    
    
		for(int i =0;i<ask.size();i++) {
    
    
			a = ask.get(i);
			a.show();
		}
	}
}

class Doctor extends Button{
    
    
  
	public Doctor(String name) {
    
    
		super(name);
		// TODO Auto-generated constructor stub
	}

	public void getButton() {
    
    
		for(int i =0;i<ask.size();i++) {
    
    
			a = ask.get(i);
			a.back();
		}
	}
}

猜你喜欢

转载自blog.csdn.net/KQwangxi/article/details/120989014