1.客户和地址(原型模式)
设计一个客户类Customer,其中客户地址存储在地址类Address中,用浅克隆和深克隆分别实现Customer对象的复制并比较这两种克隆方式的异同。绘制类图并编程模拟实现。
浅克隆:
//designpatterns.prototype.shallowclone.Customer.java
package homework.prototype.shallowclone;
public class Customer implements Cloneable {
//为了简化设计和实现,假设一份工作周报中只有一个附件对象,实际情况中可以包含多个附件,可以通过List等集合对象来实现
private Address address;
private String name;
public void setAttachment(Address address) {
this.address = address;
}
public void setName(String name) {
this.name = name;
}
public Address getAttachment() {
return (this.address);
}
public String getName() {
return (this.name);
}
//使用clone()方法实现浅克隆
public Customer clone() {
Object obj = null;
try {
obj = super.clone();
return (Customer)obj;
}
catch(CloneNotSupportedException e) {
System.out.println("不支持复制!");
return null;
}
}
}
public class Address {
private String city;
public void setCity(String city) {
this.city = city;
}
public String getCity() {
return this.city;
}
}
public class Client {
public static void main(String args[]) {
Customer customer_previous, customer_new;
customer_previous = new Customer(); //创建原型对象
Address address = new Address(); //创建地址对象
customer_previous.setAttachment(address); //将地址添加到客户中
customer_new = customer_previous.clone(); //调用克隆方法创建克隆对象
//比较周报
System.out.println("客户是否相同? " + (customer_previous == customer_new));
//比较附件
System.out.println("地址是否相同? " + (customer_previous.getAttachment() == customer_new.getAttachment()));
}
}
深克隆:
//designpatterns.prototype.deepclone.Customer.java
package homework.prototype.deepclone;
import java.io.*;
public class Customer implements Serializable {
private Address address;
private String name;
public void setAttachment(Address address) {
this.address = address;
}
public void setName(String name) {
this.name = name;
}
public Address getAttachment() {
return (this.address);
}
public String getName() {
return (this.name);
}
//使用序列化技术实现深克隆
public Customer deepClone() throws IOException, ClassNotFoundException, OptionalDataException {
//将对象写入流中
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bao);
oos.writeObject(this);
//将对象从流中取出
ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return (Customer)ois.readObject();
}
}
public class Address implements Serializable {
private String city;
public void setCity(String city) {
this.city = city;
}
public String getCity() {
return this.city;
}
}
public class Client {
public static void main(String args[]) {
Customer customer_previous, customer_new = null;
customer_previous = new Customer(); //创建原型对象
Address address = new Address(); //创建附件对象
customer_previous.setAttachment(address);
try {
customer_new = customer_previous.deepClone(); //调用深克隆方法创建克隆对象
}
catch(Exception e) {
System.err.println("克隆失败!");
}
//比较周报
System.out.println("客户是否相同? " + (customer_previous == customer_new));
//比较附件
System.out.println("地址是否相同? " + (customer_previous.getAttachment() == customer_new.getAttachment()));
}
}
2.OA系统(适配器模式)
某OA系统需要提供一个加密模块,将用户机密信息(例如口令、邮箱等)加密之后再存储在数据库中,系统已经定义好了数据库操作类。为了提高开发效率,现需要重用已有的加密算法,这些算法封装在一些由第三方提供的类中,有些甚至没有源代码。
试使用适配器模式设计该加密模块,实现在不修改现有类的基础上重用第三方加密方法。要求绘制相应的类图并编程模拟实现,需提供对象适配器和类适配器两套实现方案。
package homework.adapterOA;
// 测试适配器模式
public class Client {
public static void main(String[] args) {
// 使用对象适配器
ThirdPartyEncryptor thirdPartyEncryptor = new ThirdPartyEncryptor();
ObjectAdapter objectAdapter = new ObjectAdapter(thirdPartyEncryptor);
objectAdapter.saveData("口令");
System.out.println();
// 使用类适配器
ClassAdapter classAdapter = new ClassAdapter();
classAdapter.saveData("邮箱");
}
}
// 类适配器
class ClassAdapter extends ThirdPartyEncryptor implements DatabaseOperation {
@Override
public void saveData(String data) {
String encryptedData = encryptData(data);
System.out.println("保存加密数据: " + encryptedData);
}
}
// 对象适配器
class ObjectAdapter implements DatabaseOperation {
private ThirdPartyEncryptor thirdPartyEncryptor;
public ObjectAdapter(ThirdPartyEncryptor thirdPartyEncryptor) {
this.thirdPartyEncryptor = thirdPartyEncryptor;
}
@Override
public void saveData(String data) {
String encryptedData = thirdPartyEncryptor.encryptData(data);
System.out.println("保存加密数据: " + encryptedData);
}
}
// 数据库操作类
public interface DatabaseOperation {
public default void saveData(String data) {
System.out.println("保存数据: " + data);
}
}
// 第三方加密类
class ThirdPartyEncryptor {
public String encryptData(String data) {
// 实际加密算法的实现
System.out.println("使用第三方算法加密数据");
return "加密: " + data;
}
}
3.绘制图像(桥接模式)
某图形绘制软件提供了多种不同类型的图形,例如圆形、三角形、长方形等,并为每种图形提供了多种样式,例如平面图形、立体图形等,该软件还需经常增加新的图形及新的图形样式。现采用桥接模式设计该图形绘制软件,绘制对应的类图并编程模拟实现。
//客户端测试类
public class Client {
public static void main(String args[]) {
GraphicType graphicType = new Circle();
GraphicStyle style = new ThreedimensionalGraphics();
// GraphicType graphicType = (GraphicType)XMLUtil.getBean("graphicType");
// GraphicStyle imp = (GraphicStyle)XMLUtil.getBean("os");
graphicType.setGraphicStyle(style);
graphicType.setType();
}
}
public class Circle extends GraphicType {
public void setType() {
System.out.println("圆形");
}
}
public class Rectangle extends GraphicType {
public void setType() {
System.out.println("长方形");
}
}
public class Triangle extends GraphicType {
public void setType() {
System.out.println("三角形");
}
}
//抽象操作系统实现类,充当实现类接口
public interface GraphicStyle {
public void selStyle();
}
public abstract class GraphicType {
protected GraphicStyle style;
//注入实现类接口对象
public void setGraphicStyle(GraphicStyle style) {
style.selStyle();
}
public abstract void setType();
}
public class FlatGraphics implements GraphicStyle {
public void selStyle() {
//调用Windows系统的绘制函数绘制像素矩阵
System.out.print("绘制平面图形:");
}
}
public class ThreedimensionalGraphics implements GraphicStyle {
public void selStyle() {
//调用Linux系统的绘制函数绘制像素矩阵
System.out.print("绘制立体图形:");
}
}
4.
某移动社交软件计划增加一个群组(Group)功能。通过设置,用户可以将自己的动态信息,包括最新动态、新上传的视频以及分享的链接等,分享给某个特定的成员(Member),也可以分享给某个群组中的所有成员;用户可以将成员添加至某个指定的群组;此外,还允许用户在一个群组中添加子群组,以便更加灵活地实现面向特定人群的信息共享。
现采用组合模式设计该群组功能,绘制对应的类图并编程模拟实现。
//designpatterns.composite.Client.java
package homework.composite;
public class Client {
public static void main(String args[]) {
//针对抽象构件编程
Component member1,member2,group1,group2;
group1 = new Group("小组1");
group2 = new Group("小组2");
member1 = new Member("小明");
member2 = new Member("小花");
group1.add(member1);
group1.add(group2);
group2.add(member2);
member1.share();
group1.share();
}
}
public abstract class Component {
public abstract void add(Component file);
public abstract void remove(Component file);
public abstract Component getChild(int i);
public abstract void share();
}
public class Group extends Component {
//定义集合fileList,用于存储AbstractFile类型的成员
private ArrayList<Component> group=new ArrayList<Component>();
private String name;
public Group(String name) {
this.name = name;
}
public void add(Component file) {
group.add(file);
}
public void remove(Component file) {
group.remove(file);
}
public Component getChild(int i) {
return (Component)group.get(i);
}
public void share() {
System.out.println("给" + name + "群组全部成员进行分享"); //模拟杀毒
//递归调用成员构件的killVirus()方法
for(Object obj : group) {
((Component)obj).share();
}
}
}
public class Member extends Component {
private String name;
public Member(String name) {
this.name = name;
}
public void add(Component file) {
System.out.println("对不起,不支持该方法!");
}
public void remove(Component file) {
System.out.println("对不起,不支持该方法!");
}
public Component getChild(int i) {
System.out.println("对不起,不支持该方法!");
return null;
}
public void share() {
//模拟杀毒
System.out.println("给成员" + name + "分享");
}
}
5.
某移动OA系统需要增加一项功能:
(1) 对于尚未处理完毕的文件,需要发送一条信息用于提示相应的用户,从业务的重要等级分析,所发送的消息包括普通消息(Common Message)、加急消息(Urgent Message)和特级消息(Emergency Message)等多种类型,此外,系统需要提供系统内短消息(Short Message)、电子邮件(Email Message)和手机短信息(Mobile Message)等多种发送方式。
(2) 通过电子邮件和手机短信息来发送提示消息时可以调用已有API来实现,系统已提供所需的电子邮件处理类(EmailHandler)和手机短信息处理类(MobileMessageHandler)。
根据以上描述,选择两种合适的设计模式设计该信息提示功能,请给出这两种设计模式的名称和定义,并结合实例绘制解决方案的结构图(类名、方法名和属性名可自行定义)。