目录
任务一
1 任务要求
某会议管理系统的“会议通知发送”模块说明如下:
(1)行政管理人员可以给某个或某些员工(Employee)发送会议通知,也可以给某个部门(Department)发送通知,如果给某个部门发送通知,将逐个给该部门每个员工发送会议通知。
(2)如果员工或部门希望能够收到会议通知,必须先注册到一个会议列表(MeetingList)中,在发送通知时,系统将遍历会议列表,逐个将会议通知发送给注册用户(User)。
根据以上说明,使用组合模式与观察者模式设计该“会议通知发送”模块,请给出设计模式的定义,并绘制类结构图(类图解释)及编写相应代码。
2 任务实现
(1)设计模式的定义
组合模式:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。组合模式表示对象的全部或部分层次,让客户端忽略层次之间的差异,方便对整个层次结构进行控制。
观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。发生改变的对象称为观察目标,被通知的对象称为观察者,一个观察目标可以对应多个观察者。
(2)类结构图
User类在组合模式中充当抽象构件类,为Employee和Department声明接口,在抽象构建中定义了访问及管理它的子构件的方法:增加子构件add()、删除子构件remove()、获取子构件getUser()等。在观察者模式中充当抽象观察者,其中声明了action()方法,对观察目标的改变作出反应。
Department部门类在组合模式充当容器构件类,它提供一个集合用于存储子结点,实现类在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子结点的业务方法。在观察者模式中充当具体观察者,实现了在抽象观察者中定义的action()方法。
Employee员工类在组合模式中充当叶子构件类,它实现了在抽象构件中定义的行为。对于那些访问及管理子构件的方法,可以通过抛出异常、提示错误等方式进行处理。在观察者模式中充当具体观察者,实现了在抽象观察者中定义的action()方法。
MeetingList会议列表类,在观察者模式中充当目标类,其中定义了一个观察者集合,提供了一系列方法来增加和删除观察者对象,同时它定义了通知方法sendNotification()。
(3)程序代码
抽象构建和抽象观察者User类:
#抽象构建和抽象观察者User类:
public abstract class User {
protected String name;
public abstract void add(User user);
public abstract void remove(User user);
public abstract User getUser(int index);
public abstract void action(String info);
public String getName() {
return name;
}
}
#容器构建和具体观察者Employee类:
public class Employee extends User{
public Employee(String name) {
this.name = name;
}
@Override
public void add(User user) {
throw new IllegalArgumentException("不支持此方法!");
}
@Override
public User getUser(int index) {
throw new IllegalArgumentException("不支持此方法!");
}
@Override
public void remove(User user) {
throw new IllegalArgumentException("不支持此方法!");
}
@Override
public void action(String message) {
System.out.print(name + "收到会议通知!");
System.out.println("通知内容:" + message);
}
}
#容器构建和具体观察者Department类:
public class Department extends User{
private List<User> members = new ArrayList<>();
public Department(String name) {
this.name = name;
}
@Override
public void add(User user) {
members.add(user);
}
@Override
public void remove(User user) {
members.remove(user);
}
@Override
public User getUser(int index) {
return members.get(index);
}
@Override
public void action(String message) {
for(Object member : members) {
((User)member).action(message);
}
}
}
#目标MeetingList类:
public class MeetingList {
private List<User> users = new ArrayList<>();
public void addUser(User user) {
System.out.println(user.getName() + "注册到会议列表中!");
users.add(user);
}
public void removeUser(User user) {
System.out.println(user.getName() + "退出会议列表!");
users.remove(user);
}
public void sendNotification() {
String message = "于6月1日14:30在大厅召开会议";
for (Object user : users) {
((User)user).action(message);
}
}
}
#客户端Client类:
public class Client {
public static void main(String[] args) {
Department department1, department2;
Employee employee1, employee2, employee3, employee4, employee5;
department1 = new Department("研发组");
department2 = new Department("测试组");
employee1 = new Employee("张三");
employee2 = new Employee("李四");
employee3 = new Employee("王五");
employee4 = new Employee("赵六");
employee5 = new Employee("吴七");
department1.add(employee1);
department1.add(employee2);
department2.add(employee3);
department2.add(employee4);
MeetingList meetingList = new MeetingList();
meetingList.addUser(department1);
meetingList.addUser(department2);
meetingList.addUser(employee5);
meetingList.sendNotification();
}
}
客户端Client运行结果如下所示:
任务二
1 任务要求
现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReader),如GIF图片读取器(GifReader)用于读取GIF格式图片、JPEG图片读取器(JPEG)用于读取JPEG格式的图片。图片读取器对象通过图片读取器工厂ImageReaderFactory来创建。请使用工厂方法模式实现该程序的设计,绘制类结构图(类图解释)及编写相应代码。
2 任务实现
(1)设计模式的定义
工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
工厂方法模式简称工厂模式,又可称作虚拟构造器模式。它是一种创建型模型。工厂父类负责定义创建产品对象的公共接口,而工厂子类负责生成具体的产品对象,通过工厂子类来确定究竟应该实例化哪一个具体产品类。
(2)类结构图
ImageReader为抽象产品,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。声明了抽象方法read()。
GifReader类为具体产品类,它GifReader类实现了抽象产品ImageReader,实现Gif的read方法。具体产品GifReader类由专门的具体工厂GifReaderFactory类创建,具体工厂GifReaderFactory类和具体产品GifReader类之间一一对应。
JPEG类为具体产品类,它JPEG类实现了抽象产品ImageReader,实现JPEG的read方法。具体产品JPEG类由专门的具体工厂JPEGFactory类创建,具体工厂JPEGFactory类和具体产品JPEG类之间一一对应。
ImageReaderFactory为抽象工厂类,在抽象工厂类ImageReaderFactory中声明了工厂方法getImgerReader(),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现它。
GifReaderFactory类为具体工厂类,它GifReaderFactory类是抽象工厂类ImageReaderFactory的子类,实现了在抽象工厂ImageReaderFactory中声明的工厂方法createImgerReader,并可由客户端Client类调用,返回一个具体产品类的实例imageReader。
JPEGFactory类为具体工厂类,它JPEGFactory类是抽象工厂类ImageReaderFactory的子类,实现了在抽象工厂ImageReaderFactory中声明的工厂方法getImgerReader(),并可由客户端Client类调用,返回一个具体产品类的实例imageReader。
(3)程序代码
#抽象产品ImageReader类:
public abstract class ImageReader {
public abstract void read() ;
}
#具体产品GifReader类 :
public class GifReader extends ImageReader {
@Override
public void read() {
System.out.println("读取Gif格式图片!!!");
}
}
#具体产品JPEG类:
public class JPEG extends ImageReader {
@Override
public void read() {
System.out.println("读取JPEG格式图片!!!");
}
}
#抽象工厂ImageReaderFactory类:
public abstract class ImageReaderFactory {
public abstract ImageReader createImageReader() ;
}
#具体工厂GifReaderFactory类:
public class GifReaderFactory extends ImageReaderFactory {
@Override
public ImageReader createImageReader() {
return new GifReader();
}
}
#具体工厂JPEGFactory类:
public class JPEGFactory extends ImageReaderFactory {
@Override
public ImageReader createImageReader() {
return new JPEG();
}
}
#客户端Client类:
public class Client {
public static void main(String[] args) {
ImageReaderFactory imageReaderFactory1 = new GifReaderFactory();
ImageReaderFactory imageReaderFactory2 = new JPEGFactory();
imageReaderFactory1.createImageReader().read();
imageReaderFactory2.createImageReader().read();
}
}
客户端Client运行结果如下所示:
任务三
1 任务要求
应用软件所提供的桌面快捷方式是快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示,通过调用快捷方式的run()方法将调用应用软件的run()方法。使用代理模式模拟该过程,绘制类图(类图解释)并编程模拟实现。
2 任务实现
(1)设计模式的定义
代理模式:给某个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。代理模式是一种对象结构型模式。在代理模式中引入一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介作用,它去掉客户不能看到的内容和服务或者增添客户需要的新服务。
(2)类结构图
AbstractApplication类为抽象主题角色,定义了所有应用程序共有的行为和一些可选的实现。其中run()抽象方法,需由继承该抽象类的具体类实现,用于启动应用程序。客户端通常针对抽象角色进行编程。
RealApplication类为真是主题角色,继承自AbstractApplication类,实现具体的应用程序逻辑,是代理角色所代表的真实对象,run()方法是覆盖抽象类中的抽象方法,实现具体的应用程序启动逻辑。initialize()和shutdown()这两个方法可以选择性地覆盖以提供特定于应用的初始化和关闭行为。
ShortcutProxy类为代理类,充当实际应用程序RealApplication的代理,控制对实际应用程序的访问。它包含了对真实主题引用,从而在任何时候操作真实主题角色,run()方法调用realapp.run()来启动实际的应用程序,同时可以添加如日志记录、安全检查等前置或后置处理逻辑。
(3)程序代码
#抽象主题角色AbstractApplication类:
public abstract class AbstractApplication {
public abstract void run();
public abstract void initialize();
public abstract void shutdown();
}
#真实主题角色RealApplication类:
public class RealApplication extends AbstractApplication {
@Override
public void run() {
System.out.println("应用程序正在运行...");
}
@Override
public void initialize() {
System.out.println("应用程序初始化...");
}
@Override
public void shutdown() {
System.out.println("应用程序关闭...");
}
}
#代理ShortcutProxy类:
public class ShortcutProxy extends AbstractApplication {
private RealApplication realApp;
public ShortcutProxy() {
this.realApp = new RealApplication();
}
@Override
public void run() {
System.out.println("启动中,请稍候...");
realApp.run(); // 调用实际应用程序的run方法
}
@Override
public void initialize() {
realApp.initialize();
}
@Override
public void shutdown() {
realApp.shutdown(); // 清理资源关闭程序
}
}
#客户端Client类:
public class Client {
public static void main(String[] args) {
AbstractApplication app = new ShortcutProxy();
app.initialize();
app.run();
app.shutdown();
}
}
客户端Client运行结果如下所示:
任务四
1 任务要求
在军队中,一般根据战争规模的大小和重要性由不同级别的长官(Officer)来下达作战命令,情报人员向上级递交军情(如敌人的数量),作战命令需要上级批准,如果直接上级不具备下达命令的权力,则上级又传给上级,直到有人可以决定为止。现使用职责链模式来模拟该过程,客户类(Client)模拟情报人员,首先向级别最低的班长(Banzhang)递交任务书(Mission),即军情,如果超出班长的权力范围,则传递给排长(Paizhang),排长如果也不能处理则传递给营长(Yingzhang),如果营长也不能处理则需要开会讨论。我们设置这几
级长官的权力范围分别是:
- 敌人数量<10,班长下达作战命令。
- 10≤敌人数量<50,排长下达作战命令。
- 50≤敌人数量<200,营长下达作战命令。
- 敌人数量≥200,需要开会讨论再下达作战命令。
绘制类图(类图解释)并编程实现。
2 任务实现
(1)设计模式的定义
职责链模式:避免讲一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接受请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
(2)类结构图
Handler为抽象处理者,定义了一个抽象处理者类型的对象successor作为其对下家的引用,通过该引用处理者可以连成一条链。定义了两个抽象方法,一个是canHandle()来确定是否可以处理给定的任务。另一个是handleMission()来处理给定的任务。
Banzhang、Paizhang和Yingzhang类为具体处理者类,是Handler抽象处理者的子类,可以处理用户请求,在处理请求之前使用canHandle()方法根据敌人数量判断是否可以处理任务,如果可以处理请求就处理它,否则将请求转发给后继者。
Command类为普通类,它的getCommandType()方法用来获取命令类型。execute()方法来执行命令的具体操作。
Mission类为普通类,它的getEnemyCount()方法来获取敌人数量。getCommand()方法来获取命令对象。
(3)程序代码
#抽象处理者Handler类:
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract boolean canHandle(Mission mission);
public abstract void handleMission(Mission mission);
}
#具体处理者Banzhang类:
public class Banzhang extends Handler {
public boolean canHandle(Mission mission) {
return mission.getEnemyCount() < 10;
}
@Override
public void handleMission(Mission mission) {
if (canHandle(mission)) {
System.out.println("班长下达作战命令: " + mission.getCommand().getCommandType());
mission.getCommand().execute();
} else {
if (successor != null) {
successor.handleMission(mission);
}
}
}
}
#具体处理者Paizhang类:
public class Paizhang extends Handler {
@Override
public boolean canHandle(Mission mission) {
return mission.getEnemyCount() >= 10 && mission.getEnemyCount() < 50;
}
@Override
public void handleMission(Mission mission) {
if (canHandle(mission)) {
System.out.println("排长下达作战命令: " + mission.getCommand().getCommandType());
mission.getCommand().execute();
} else {
if (successor != null) {
successor.handleMission(mission);
}
}
}
}
#具体处理者Yingzhang类:
public class Yingzhang extends Handler {
@Override
public boolean canHandle(Mission mission) {
return mission.getEnemyCount() >= 50 && mission.getEnemyCount() < 200;
}
@Override
public void handleMission(Mission mission) {
if (canHandle(mission)) {
System.out.println("营长下达作战命令: " + mission.getCommand().getCommandType());
mission.getCommand().execute();
} else {
if (successor != null) {
successor.handleMission(mission);
} else {
System.out.println("敌人数量过多,需要开会讨论再下达作战命令");
}
}
}
}
#Command普通类:
public class Command {
private String commandType;
public Command(String commandType) {
this.commandType = commandType;
}
public String getCommandType() {
return commandType;
}
public void execute() {
System.out.println("执行命令: " + commandType);
}
}
#Mission普通类:
public class Mission {
private int enemyCount;
private Command command;
public Mission(int enemyCount, Command command) {
this.enemyCount = enemyCount;
this.command = command;
}
public int getEnemyCount() {
return enemyCount;
}
public Command getCommand() {
return command;
}
}
#客户端Client类:
public class Client {
public static void main(String[] args) {
Handler banzhang = new Banzhang();
Handler paizhang = new Paizhang();
Handler yingzhang = new Yingzhang();
banzhang.setSuccessor(paizhang);
paizhang.setSuccessor(yingzhang);
// 创建任务,模拟敌人数量不同的情景
Mission smallMission = new Mission(5, new Command("侦察"));
Mission mediumMission = new Mission(20, new Command("小规模进攻"));
Mission largeMission = new Mission(100, new Command("全面进攻"));
Mission tooLargeMission = new Mission(300, new Command("撤退"));
// 发起任务处理请求
System.out.println("处理小规模任务:");
banzhang.handleMission(smallMission);
System.out.println("处理中等规模任务:");
banzhang.handleMission(mediumMission);
System.out.println("处理大规模任务:");
banzhang.handleMission(largeMission);
System.out.println("处理超大规模任务:");
banzhang.handleMission(tooLargeMission);
}
}
客户端Client运行结果如下所示: