12.7 实验二十四模板方法模式 实验二十五访问者模式
实验 24:模板方法模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解模板方法模式的动机,掌握该模式的结构;
2、能够利用模板方法模式解决实际问题。
[实验任务一]:数据库连接
对数据库的操作一般包括连接、打开、使用、关闭等步骤,在数据库操作模板类中我们定义了connDB()、openDB()、useDB()、closeDB()四个方法分别对应这四个步骤。对于不同类型的数据库(如SQL Server和Oracle),其操作步骤都一致,只是连接数据库connDB()方法不同,现使用模板方法模式对其进行设计。
实验要求:
1.画出对应的类图;
2.提交源代码;
3.注意编程规范。

1. DatabaseTemplate.java
public abstract class DatabaseTemplate {
/**
* 模板方法:定义数据库操作的固定步骤(连接→打开→使用→关闭)
* 设为final防止子类重写流程,保证步骤一致性
*/
public final void execute() {
connDB(); // 步骤1:连接数据库(子类实现)
openDB(); // 步骤2:打开数据库(通用实现)
useDB(); // 步骤3:使用数据库(通用实现)
closeDB(); // 步骤4:关闭数据库(通用实现)
}
/**
* 抽象方法:连接数据库(子类实现具体数据库的连接逻辑)
*/
protected abstract void connDB();
/**
* 具体方法:打开数据库(通用逻辑)
*/
protected void openDB() {
System.out.println("通用操作:打开数据库连接,初始化会话参数");
}
/**
* 具体方法:使用数据库(通用逻辑)
*/
protected void useDB() {
System.out.println("通用操作:执行SQL语句,处理数据查询/更新");
}
/**
* 具体方法:关闭数据库(通用逻辑)
*/
protected void closeDB() {
System.out.println("通用操作:关闭数据库连接,释放资源\n");
}}
2. SQLServerDB.java
public class SQLServerDB extends DatabaseTemplate {
@Override
protected void connDB() {
System.out.println("SQL Server特有操作:通过JDBC连接SQL Server,URL格式为jdbc:sqlserver://<主机>:<端口>;databaseName=<库名>");
}}
3. OracleDB.java
public class OracleDB extends DatabaseTemplate {
@Override
protected void connDB() {
System.out.println("Oracle特有操作:通过JDBC连接Oracle,URL格式为jdbc:oracle:thin:@<主机>:<端口>:<SID>");
}}
4. DatabaseTemplateTest.java
public class DatabaseTemplateTest {
public static void main(String[] args) {
// 1. 操作SQL Server数据库
System.out.println("===== 执行SQL Server数据库操作 =====");
DatabaseTemplate sqlServer = new SQLServerDB();
sqlServer.execute();
// 2. 操作Oracle数据库
System.out.println("===== 执行Oracle数据库操作 =====");
DatabaseTemplate oracle = new OracleDB();
oracle.execute();
}}
实验 25:访问者模式
本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:
1、理解访问者模式的动机,掌握该模式的结构;
2、能够利用访问者模式法解决实际问题。
[实验任务一]:打包员
在我们课堂上的“购物车”的例子中,增加一个新的访问者:打包员,负责对购物车中货物装包。
实验要求:
1.画出对应的类图;
2.提交源代码;
3. 注意编程规范。

1. ProductElement.java
public interface ProductElement {
/**
* 接受访问者访问的方法
* @param visitor 访问者对象
*/
void accept(Visitor visitor);}
2. Book.java
public class Book implements ProductElement {
// 商品名称
private final String name;
// 商品价格
private final double price;
// 书籍重量(kg)
private final double weight;
/**
* 构造方法:初始化书籍属性
* @param name 书籍名称
* @param price 书籍价格
* @param weight 书籍重量(kg)
*/
public Book(String name, double price, double weight) {
this.name = name;
this.price = price;
this.weight = weight;
}
// Getter方法
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public double getWeight() {
return weight;
}
@Override
public void accept(Visitor visitor) {
// 调用访问者的书籍访问方法,完成双重分派的第二重绑定
visitor.visit(this);
}}
3. ElectronicProduct.java
public class ElectronicProduct implements ProductElement {
// 商品名称
private final String name;
// 商品价格
private final double price;
// 电子产品尺寸(小/中/大)
private final String size;
/**
* 构造方法:初始化电子产品属性
* @param name 电子产品名称
* @param price 电子产品价格
* @param size 电子产品尺寸(小/中/大)
*/
public ElectronicProduct(String name, double price, String size) {
this.name = name;
this.price = price;
this.size = size;
}
// Getter方法
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public String getSize() {
return size;
}
@Override
public void accept(Visitor visitor) {
// 调用访问者的电子产品访问方法,完成双重分派的第二重绑定
visitor.visit(this);
}}
4. Visitor.java
public interface Visitor {
/**
* 访问书籍元素的方法
* @param book 书籍对象
*/
void visit(Book book);
/**
* 访问电子产品元素的方法
* @param eProduct 电子产品对象
*/
void visit(ElectronicProduct eProduct);}
5. PriceVisitor.java
public class PriceVisitor implements Visitor {
// 购物车商品总价
private double totalPrice = 0.0;
/**
* 获取计算后的商品总价
* @return 总价(元)
*/
public double getTotalPrice() {
return totalPrice;
}
@Override
public void visit(Book book) {
// 累加书籍价格
totalPrice += book.getPrice();
System.out.println("统计书籍《" + book.getName() + "》价格:" + book.getPrice() + "元");
}
@Override
public void visit(ElectronicProduct eProduct) {
// 累加电子产品价格
totalPrice += eProduct.getPrice();
System.out.println("统计电子产品《" + eProduct.getName() + "》价格:" + eProduct.getPrice() + "元");
}}
6. PackagerVisitor.java
public class PackagerVisitor implements Visitor {
// 打包详情字符串(拼接所有商品的打包信息)
private String packageDetail = "【购物车商品打包详情】\n";
/**
* 获取生成的打包详情
* @return 打包详情描述
*/
public String getPackageDetail() {
return packageDetail;
}
@Override
public void visit(Book book) {
// 书籍打包规则:重量≤0.5kg用薄纸盒,>0.5kg用厚纸盒+防震膜
String packageRule;
if (book.getWeight() <= 0.5) {
packageRule = "薄纸盒包装(轻便型)";
} else {
packageRule = "厚纸盒+防震膜包装(防压型)";
}
packageDetail += "书籍《" + book.getName() + "》- 重量:" + book.getWeight() + "kg → " + packageRule + "\n";
}
@Override
public void visit(ElectronicProduct eProduct) {
// 电子产品打包规则:按尺寸选择包装类型
String packageRule;
switch (eProduct.getSize()) {
case "小":
packageRule = "气泡袋+小纸盒包装(便携型)";
break;
case "中":
packageRule = "泡沫垫+中纸箱包装(防护型)";
break;
case "大":
packageRule = "定制泡沫+大纸箱+木架包装(加固型)";
break;
default:
packageRule = "通用防震包装(默认型)";
}
packageDetail += "电子产品《" + eProduct.getName() + "》- 尺寸:" + eProduct.getSize() + " → " + packageRule + "\n";
}}
7. ShoppingCart.java
/public class ShoppingCart {
// 商品元素列表(存储购物车中的所有商品)
private final List<ProductElement> products = new ArrayList<>();
/**
* 向购物车添加商品的方法
* @param product 商品元素对象
*/
public void addProduct(ProductElement product) {
products.add(product);
}
/**
* 接受访问者访问的方法,遍历所有商品并调用其accept方法
* @param visitor 访问者对象
*/
public void accept(Visitor visitor) {
for (ProductElement product : products) {
product.accept(visitor);
}
}}
8. ShoppingCartVisitorTest.java
public class ShoppingCartVisitorTest {
public static void main(String[] args) {
// 1. 创建购物车并添加商品
ShoppingCart cart = new ShoppingCart();
cart.addProduct(new Book("Java编程思想", 108.0, 0.8));
cart.addProduct(new ElectronicProduct("无线蓝牙耳机", 299.0, "小"));
cart.addProduct(new ElectronicProduct("15.6英寸笔记本电脑", 5999.0, "大"));
// 2. 价格统计访问者处理购物车
System.out.println("===== 购物车商品价格统计 =====");
PriceVisitor priceVisitor = new PriceVisitor();
cart.accept(priceVisitor);
System.out.println("购物车商品总价:" + priceVisitor.getTotalPrice() + "元\n");
// 3. 打包员访问者处理购物车
System.out.println("===== 购物车商品打包详情 =====");
PackagerVisitor packagerVisitor = new PackagerVisitor();
cart.accept(packagerVisitor);
System.out.println(packagerVisitor.getPackageDetail());
}}

浙公网安备 33010602011771号