命令(Command Pattern)模式
将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。将"行为请求者"与"行为实现者"解耦。
优点:
1、降低了系统耦合度。
2、新的命令可以很容易添加到系统中去。
缺点:
使用命令模式可能会导致某些系统有过多的具体命令类。
优使用场景:
认为是命令的地方都可以使用命令模式。
1、GUI中每一个按钮都是一条命令。
2、模拟 CMD。
具体实现:创建Order作为命令的接口,然后创建作为请求的 Stock 类。实体命令类 BuyStock和 SellStock,实现了 Order 接口,将执行实际的命令处理。创建作为调用对象的类Broker,它接受订单并能下订单。
//创建一个命令接口
public interface Order {
void execute();
}
//创建一个请求类
public class Stock {
private String name = "ABC";
private int quantity = 10;
public void buy(){
System.out.println("Stock [ Name: "+name+",
Quantity: " +quantity +" ] bought");
}
public void sell(){
System.out.println("Stock [ Name: "+name+",
Quantity: " +quantity +" ] sold");
}
}
//创建实现了Order接口的实体类
public class BuyStock implements Order {
private Stock abcStock;
public BuyStock(StockabcStock){
this.abcStock = abcStock;
}
public void execute() {
abcStock.buy();
}
}
public class SellStock implements Order {
private Stock abcStock;
public SellStock(StockabcStock){
this.abcStock = abcStock;
}
public void execute() {
abcStock.sell();
}
}
//创建命令调用类,Broker对象使用命令模式,基于命令的类型确定哪个对象执行哪个命令
public class Broker {
private ListorderList =new ArrayList();
public void takeOrder(Order order){
orderList.add(order);
}
public void placeOrders(){
for (Order order : orderList) {
order.execute();
}
orderList.clear();
}
}
//使用Broker类来接受并执行命令
public class Client {
public static void main(String[] args) {
StockabcStock = new Stock();
BuyStock buyStockOrder = newBuyStock(abcStock);
SellStock sellStockOrder = newSellStock(abcStock);
Broker broker = new Broker();
broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);
broker.placeOrders();
}
}
/*output
Stock [Name: ABC, Quantity: 10 ] bought
Stock [Name: ABC, Quantity: 10 ] sold
*/
责任链(Chain ofResponsibility Pattern)模式
很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
3、可能不容易观察运行时的特征,有碍于除错。
使用场景:
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
具体实现:
创建抽象类 AbstractLogger,带有详细的日志记录级别。然后创建三种类型的记录器,都扩展了AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录。
//创建抽象的记录器类
public abstract class AbstractLogger{
public static int INFO = 1; //一级日志记录
public static int DEBUG = 2; //二级日志记录
public static int ERROR = 3; //三级日志记录
protected int level;
//责任链中的下一个元素
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLoggernextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message) {
if (this.level <= level) {
write(message);
}
if (nextLogger != null) {
nextLogger.logMessage(level, message);
}
}
//不同级别的记录方法不一样,添加各自处理行为
abstract protected void write(String message);
}
//创建扩展了该记录器类的实体类,控制台处理器
public class ConsoleLoggerextends AbstractLogger{
public ConsoleLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println(“Standard Console::Logger :” + message);
}
}
//文件处理器
public class FileLogger extends AbstractLogger {
public FileLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("File Console::Logger" + message);
}
}
//error日志处理器
public class ErrorLoggerextends AbstractLogger{
public ErrorLogger(int level) {
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " + message);
}
}
//创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器
//每个记录器中的下一个记录器代表的是链的一部分
public class ChainPatternDemo{
public static AbstractLoggergetChainOfLoggers() {
AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
AbstractLogger fileLogger = newFileLogger(AbstractLogger.DEBUG);
AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);
return errorLogger;
}
}
public class Client {
public static void main(String[] args) {
AbstractLogger logger = ChainPatternDemo.getChainOfLoggers();
logger.logMessage(1, “一级日志记录”);
logger.logMessage(2, "二级日志记录");
logger.logMessage(3, "三级日志记录");
}
}
更多技术分享,公众号“专注一行代码”,ID zzyhdm