建设网站技术要求,网易企业邮箱格式,如何建立一个网站链接把文件信息存里,建服务网站需要多少钱文章目录 前言一、命令模式二、访问者模式三、迭代器模式 前言 本篇是关于设计模式中命令模式、访问者模式、以及迭代器模式的学习笔记。 一、命令模式 命令模式是一种行为型设计模式#xff0c;其核心目的在于将命令的发送者和接受者解耦#xff0c;提供一个中间层对命令进行… 文章目录 前言一、命令模式二、访问者模式三、迭代器模式 前言 本篇是关于设计模式中命令模式、访问者模式、以及迭代器模式的学习笔记。 一、命令模式 命令模式是一种行为型设计模式其核心目的在于将命令的发送者和接受者解耦提供一个中间层对命令进行统一的管理请求的发送者不需要知道接收者的具体实现而只需依赖一个抽象的命令接口。 命令模式通常包括以下的角色
抽象/接口命令层定义了执行命令的抽象方法例如执行撤销。具体命令类继承/实现了命令层对命令的具体内容做一个描述。接收者实际执行操作的对象包含与请求相关的逻辑。调用者调用命令对象以触发请求的执行。客户端创建具体的命令对象并将其绑定到调用者上。 举一个生活中的案例假设对于家电想要通过一个万能遥控器去控制某个家电的开/关而不需要每个家电都配一个遥控器则可以将开关设为具体命令类
/*** 命令抽象类*/
public interface Command {/*** 执行命令*/void execute();/*** 回滚操作*/void undo();
} 以对灯的开关操作为例开灯的命令类
/*** 开灯*/
public class LightOnCommand implements Command{private Light light;public LightOnCommand(Light light) {this.light light;}Overridepublic void execute() {light.on();}Overridepublic void undo() {light.off();}
}关灯的命令类
/*** 关灯*/
public class LightOffCommand implements Command{private Light light;public LightOffCommand(Light light) {this.light light;}Overridepublic void execute() {light.off();}Overridepublic void undo() {light.on();}
} 具体的电器有开关的操作。
public class Light {public void on(){System.out.println(把灯打开);}public void off(){System.out.println(关灯了);}
} 以及一个空的命令类
public class NoCommand implements Command{/*** 执行命令*/Overridepublic void execute() {}/*** 回滚操作*/Overridepublic void undo() {}
}命令的统一管理类主要作用
对命令组进行初始化。设置操控某一个对象的具体命令。执行具体的命令。撤销命令。
public class RemoteController {//存放各种设备的开命令Command[] onCommands;//存放各种设备的关命令Command[] offCommands;//撤销的命令Command unCommand;/*** 初始化空命令*/public RemoteController(int number) {onCommands new Command[number];offCommands new Command[number];for (int i 0; i number; i) {onCommands[i] new NoCommand();offCommands[i] new NoCommand();}}/*** 设置具体的命令** param no 设备组编号* param onCommand 具体设备组设备的开命令* param offCommand 具体设备组设备的关命令*/public void setCommand(int no, Command onCommand, Command offCommand) {onCommands[no] onCommand;offCommands[no] offCommand;}/*** 按下某个设备的开按钮** param no 设备组编号*/public void onButtonWasPushed(int no) {onCommands[no].execute();//记录本次操作便于撤销unCommand onCommands[no];}/*** 按下某个设备的关按钮** param no 设备组编号*/public void offButtonWasPushed(int no) {offCommands[no].execute();//记录本次操作便于撤销unCommand offCommands[no];}/*** 撤销*/public void undo() {unCommand.undo();}
}客户端
public class Client {public static void main(String[] args) {Light light new Light();//初始化开启电灯命令LightOnCommand lightOnCommand new LightOnCommand(light);//初始化关闭电灯命令LightOffCommand lightOffCommand new LightOffCommand(light);//初始化遥控器面板RemoteController remoteController new RemoteController(5);remoteController.setCommand(0, lightOnCommand, lightOffCommand);System.out.println(--------开启电灯--------);remoteController.onButtonWasPushed(0);System.out.println(--------关闭电灯--------);remoteController.offButtonWasPushed(0);System.out.println(--------撤销上一步操作--------);remoteController.undo();}
}如果需要进行扩展比如电视只需要去增加一个电视机对象以及两个实现了命令接口的具体命令类最后在客户端进行初始化即可无需对命令管理类进行修改。
二、访问者模式 访问者模式是一种行为型设计模式主要用来将操作与对象结构分离。核心思想在不修改对象结构的前提下定义作用于这些对象的新操作。 访问者模式通过引入一个访问者对象将对结构中各个元素的操作从元素类中抽离出来。这样当需要添加新操作时无需修改元素类而只需添加新的访问者类访问者模式由以下几个角色组成
访问者接口声明对每种元素类型的访问操作方法。具体访问者实现访问者接口定义具体的操作逻辑。元素接口定义接受访问者对象的方法。具体元素实现元素接口在接受访问者对象的方法中调用访问者的相应方法。对象结构包含一组元素可以遍历这些元素并让访问者访问它们。 举一个生活中的案例例如在网上商城将商品加入购物车需要计算商品总价还需要获取商品的详细清单利用访问者模式可以将商品作为被访问的类
/*** 被访问的元素接口*/
public interface Item {void accept(Visitor visitor);
}/*** 被访问的元素书籍*/
public class Book implements Item {private String title;private double price;public Book(String title, double price) {this.title title;this.price price;}public String getTitle() {return title;}public double getPrice() {return price;}Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}/*** 被访问的元素电子产品*/
public class Electronic implements Item {private String name;private double price;public Electronic(String name, double price) {this.name name;this.price price;}public String getName() {return name;}public double getPrice() {return price;}Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}定义一个访问者接口层访问具体的商品书籍电子产品
public interface Visitor {void visit(Book book);void visit(Electronic electronic);
}定义计算价格和打印清单具体的行为
/*** 打印清单*/
public class ItemPrinterVisitor implements Visitor {Overridepublic void visit(Book book) {System.out.println(Book: book.getTitle() - Price: book.getPrice());}Overridepublic void visit(Electronic electronic) {System.out.println(Electronic: electronic.getName() - Price: electronic.getPrice());}
}/*** 计算书籍和电子产品的价格*/
public class PriceCalculatorVisitor implements Visitor{private double totalPrice 0;Overridepublic void visit(Book book) {totalPrice totalPricebook.getPrice();}Overridepublic void visit(Electronic electronic) {totalPrice totalPrice electronic.getPrice();}public double getTotalPrice(){return totalPrice;}
}以及具体的对象接口让访问者去操作书籍和电子产品
/*** 对象接口*/
public class ShoppingCart {private ListItem items new ArrayList();public void addItem(Item item) {items.add(item);}public void accept(Visitor visitor) {for (Item item : items) {item.accept(visitor);}}
}客户端
public class Client {public static void main(String[] args) {// 创建购物车ShoppingCart cart new ShoppingCart();cart.addItem(new Book(Spring源码深度解析, 50));cart.addItem(new Electronic(Iphone17, 6300));// 计算总价PriceCalculatorVisitor priceCalculator new PriceCalculatorVisitor();cart.accept(priceCalculator);System.out.println(Total Price: priceCalculator.getTotalPrice());// 打印清单ItemPrinterVisitor itemPrinter new ItemPrinterVisitor();cart.accept(itemPrinter);}
}这样的好处在于将具体的操作和对象结构分离后续增加具体的操作无需对对象结构进行修改。因此适用于需要对对象结构中的对象执行多种不相关的操作而操作的实现细节需要彼此独立的场景。 同时也可以体会一下如果不使用访问者模式会存在怎么样的弊端
代码耦合度高在ShoppingCart类中我们需要判断每个商品的类型并为不同类型的商品执行不同的操作。这导致了ShoppingCart 类与具体商品类型的紧密耦合。如果要新增一种商品就又要加一个条件分支。扩展性差同样地除了计算价格和打印清单如果还需要再增加一种操作那么购物车的代码还需要进行修改。
// 书籍类Book
public class Book {private String title;private double price;public Book(String title, double price) {this.title title;this.price price;}public String getTitle() {return title;}public double getPrice() {return price;}
}// 电子产品类ElectronicProduct
public class ElectronicProduct {private String name;private double price;public ElectronicProduct(String name, double price) {this.name name;this.price price;}public String getName() {return name;}public double getPrice() {return price;}
} 在购物车中直接计算总价打印清单
import java.util.ArrayList;
import java.util.List;public class ShoppingCart {private ListObject items;public ShoppingCart() {items new ArrayList();}public void addItem(Object item) {items.add(item);}public ListObject getItems() {return items;}// 计算总价public double calculateTotalPrice() {double totalPrice 0;for (Object item : items) {if (item instanceof Book) {totalPrice ((Book) item).getPrice();} else if (item instanceof ElectronicProduct) {totalPrice ((ElectronicProduct) item).getPrice();}}return totalPrice;}// 打印订单清单public void printOrderDetails() {System.out.println(Shopping Cart Details:);for (Object item : items) {if (item instanceof Book) {Book book (Book) item;System.out.println(Book: book.getTitle() , Price: book.getPrice());} else if (item instanceof ElectronicProduct) {ElectronicProduct product (ElectronicProduct) item;System.out.println(Product: product.getName() , Price: product.getPrice());}}}
}
三、迭代器模式 迭代器模式是一种行为型设计模式核心思想是将集合的遍历操作与集合的实现分离从而不暴露集合的内部结构只需要依赖一个公共的接口来访问集合中的元素。通过这种方式可以在不改变集合结构的情况下提供不同的遍历方式和逻辑通常包含以下的角色
迭代器接口定义遍历集合元素的方法可以使用JDK的Iterator接口。具体迭代器实现迭代器接口负责具体的遍历逻辑。聚合接口定义返回一个迭代器的方法。具体聚合实现聚合接口维护集合的实际数据结构并提供创建迭代器的方法。 假设现在有一个电商项目需要管理多个订单。每个订单由多个商品组成。希望能够顺序遍历订单中的商品而不暴露订单内部的实现细节首先创建一个商品的实例
public class Product {private String productName;private double price;public Product(String productName, double price) {this.productName productName;this.price price;}public String getProductName() {return productName;}public double getPrice() {return price;}
}再编写一个聚合接口
public interface Aggregate {Iterator createIterator();
} 创建具体聚合和迭代器接口
public class Order implements Aggregate{private String orderId;private Product[] items;public Order(String orderId, Product[] items) {this.orderId orderId;this.items items;}public String getOrderId() {return orderId;}public Product[] getItems() {return items;}Overridepublic Iterator createIterator() {return new OrderIterator(this);}
}
public class OrderIterator implements Iterator {private Order order;private int index;public OrderIterator(Order order) {this.order order;this.index 0;}Overridepublic boolean hasNext() {return index order.getItems().length;}Overridepublic Object next() {if (hasNext()) {return order.getItems()[index];}return null;}
}客户端创建产品并且遍历:
public class Client {public static void main(String[] args) {Product p1 new Product(产品1, 5);Product p2 new Product(产品2, 6);Product p3 new Product(产品3, 7);Order order new Order(10001, new Product[]{p1, p2, p3});Iterator iterator order.createIterator();while (iterator.hasNext()){Product next (Product) iterator.next();System.out.println(next);}}
}同时也可以对比一下不使用迭代器模式在客户端中直接遍历体会一下存在哪些弊端
客户端直接操作 Order 类的内部实现如果以后把商品的存储方式改为其他数据结构所有使用 Order 类的代码都需要修改。遍历商品数组的逻辑直接写在了客户端每个需要遍历商品的地方都必须重复写遍历逻辑。以及如果需要进行不同方式的遍历需要修改遍历逻辑以及所有使用到的客户端的代码。
public class Product {private String productName;private double price;public Product(String productName, double price) {this.productName productName;this.price price;}public String getProductName() {return productName;}public double getPrice() {return price;}
}public class Order {private String orderId;private Product[] items;public Order(String orderId, Product[] items) {this.orderId orderId;this.items items;}public String getOrderId() {return orderId;}public Product[] getItems() {return items;}
}public class Client {public static void main(String[] args) {// 创建产品Product p1 new Product(Laptop, 1000);Product p2 new Product(Smartphone, 800);Product p3 new Product(Headphones, 150);// 创建订单Product[] products {p1, p2, p3};Order order new Order(O1001, products);// 直接在客户端遍历商品Product[] items order.getItems();for (int i 0; i items.length; i) {System.out.println(Product: items[i].getProductName() , Price: items[i].getPrice());}}
}