Java Tip: 实现Command模式

工程师职级胜任力框架 一、前言 尽管这些年国内的IT行业发展迅速,但是仍然欠缺一套比较综合性的面向工程师的职级胜任力框架,造成国内很多工程师大都一心只想成为技术大牛,而忽视了自己全方位的工程师职业素养和能力的培养。 最近我有幸读到了Circle CI公司分享的工程胜任力矩阵,发现这份文档就是一份比较贴合互联网研发型企业的工程师职级胜任力框架,于是我在它的基础上,重新整理出了一份更适合国内工程师阅读的《工程师职级胜任力框架》,并把它分享在波波的github站点上,希望这份文档对工程师的职业开发和成长有帮助。注,Circle CI. 阅读详情

 

Java Tip: 实现Command模式

概述
有时需要向对象发送请求,但是不知道 "被请求的操作" 或 "请求的接受者" 的任何信息。在面向过程的程序设计语言中,这类通信是通过回调函数来完成的:在某个地方登记这个函数,然后在后面调用它。在面向对象程序中,command(命令)与回调函数等价,它封装了回调函数。本文演示如何在Java中实现Command模式。

---------------------------------------------------------------------------

设计模式不但可以加速面向对象工程的设计进度,而且可以提高开发小组的产出以及软件的质量。Commad模式是一种对象行为模式,它可以对发送者(sender)和接收者(receiver)完全解耦(decoupling)。("发送者" 是请求操作的对象,"接收者" 是接收请求并执行某操作的对象。有了 "解耦",发送者对接收者的接口一无所知。)这里,"请求"(request)这个术语指的是要被执行的命令。Command模式还让我们可以对 "何时" 以及 "如何" 完成请求进行改变。因此,Command模式为我们提供了灵活性和可扩展性。

在象C这样的程序设计语言中,函数指针常被用来消除庞大的switch语句。(参见 "Java Tip 30: Polymorphism and Java" 获得更详细的介绍)Java没有函数指针,所以我们可以用Command模式来实现回调函数。在下面的第一个代码示例TestCommand.java中,你将实际看到它是如何实现的。

一些开发者在其它语言中已经习惯于使用函数指针,因而他们往往禁不起诱惑,想以同样的方法使用Reflection API的Method对象。例如,在 "Java Reflection" 一文中,Paul Tremblett介绍了如何使用Reflection而不是switch语句来实现事务处理(Transaction) (参见 "相关资源" 获得Tremblett的文章和Sun的Reflection教程网址的链接)。我是不会为这样的诱惑所动的。正如Sun所指出的:在有其它更贴近于Java程序设计语言的工具满足使用要求的情况下,一般不提倡使用Reflect API。不使用Method对象,程序会更易于调试和维护。所以,你应该定义一个接口,并在类中实现它,以执行所需操作。

因此我建议,可以使用Command模式并结合Java的动态加载和绑定机制来实现函数指针。(关于Java的动态加载和绑定机制的详细介绍,参见Gosling和Henry McGilton的"The Java Language Environment -- A White Paper",列于"相关资源"。)

遵循上面的建议,我们可以运用Command模式,利用它所提供的多态性来消除庞大的switch语句,从而设计出可扩展的系统。我们还可以利用Java独有的动态加载和绑定机制来构筑动态的、并且可以动态扩展的系统。这一点在下面第二个代码示例TestTransactionCommand.java中进行说明。

Command模式使请求本身成为一个对象。这个对象和其它对象一样可以被存储和四处传递。这种模式的关键在于一个Command接口:它声明了一个接口,用于执行操作。最简单的形式下,这个接口包含一个抽象的execute操作。每个具体的Command类把接收者作为一个实例变量进行存储,从而指定了一对 "接收者" 和 "行为"。它为execute()方法提供不同的实现以进行请求调用。接收者知道如何执行请求。

如下的图1表示了Switch--一个Command对象的集合体(aggregation)。它的接口中有flipUp()和flipDown()两种操作。Switch被称为 "调用者"(invoker),因为它调用command接口中的execute操作。

具体的command,如LightOnCommand,实现command接口的execute操作。它知道去调用合适的接收者对象的操作。这种情况下它充当了一个适配器(adapter)。通过 "适配器"这一术语, 我想说明:具体的Command对象是一个简单的连接器,它连接具有不同接口的 "调用者" 和 "接收者"。

客户实例化调用者,接收者以及具体的command对象。

图2为时序图,它表示对象间的相互作用。它说明了Command如何对调用者和接收者(以及它执行的请求)解耦。客户用合适的接收者作为构造函数的参数来创建具体的command。然后,它将Command保存在调用者中。调用者回调具体的command,后者知道如何完成想要的Action()操作。

客户(代码中的主程序)创建具体的Command对象并设置它的接收者。作为一个调用者对象,Switch保存具体的Command对象。调用者通过对Command对象调用execute来发送请求。具体的Command对象对它的接收者进行操作调用,从而完成操作请求。

这里最关键的思想在于,具体的command用调用者来注册自身,调用者进行回调,在接收者身上执行命令。

Command模式示例代码
让我们来看一个简单的例子,它通过Command模式实现回调机制。

以Fan(风扇)和Light(灯)为例。我们的目标是设计一个Switch,它可以对任一个对象进行 "开" 和 "关" 的操作。Fan和Light具有不同的接口,这意味着Switch必须独立于接收者接口,或者说,它不清楚接收者的接口。为了解决这一问题,每个Switch都需要合适的command作为参数。很明显,连接到Light的Switch和连接到Fan的Switch具有不同的command。因此,Command类必须是抽象的,或者是个接口。

Switch的构造函数被调用时,它以一组合适的command作为参数。command作为Switch的私有变量保存下来。

调用flipUp()和flipDown()操作时,它们只是简单地让合适的command进行execute()操作。Switch对调用execute()后将发生些什么一无所知。

TestCommand.java
class Fan {
        public void startRotate() {
                System.out.println("Fan is rotating");
        }
        public void stopRotate() {
                System.out.println("Fan is not rotating");
        }
}
class Light {
        public void turnOn( ) {
                System.out.println("Light is on ");
        }
        public void turnOff( ) {
                System.out.println("Light is off");
        }
}
class Switch {
        private Command UpCommand, DownCommand;
        public Switch( Command Up, Command Down) {
                UpCommand = Up; // concrete Command registers itself with the invoker
                DownCommand = Down;
        }
        void flipUp( ) { // invoker calls back concrete Command, which executes the Command on the receiver
                        UpCommand . execute ( ) ;


        }
        void flipDown( ) {
                        DownCommand . execute ( );
        }
}
class LightOnCommand implements Command {
        private Light myLight;
        public LightOnCommand ( Light L) {
                myLight  =  L;
        }
        public void execute( ) {
                myLight . turnOn( );
        }
}
class LightOffCommand implements Command {
        private Light myLight;
        public LightOffCommand ( Light L) {
                myLight  =  L;
        }
        public void execute( ) {
                myLight . turnOff( );
        }
}
class FanOnCommand implements Command {
        private Fan myFan;
        public FanOnCommand ( Fan F) {
                myFan  =  F;
        }
        public void execute( ) {
                myFan . startRotate( );
        }
}
class FanOffCommand implements Command {
        private Fan myFan;

        public FanOffCommand ( Fan F) {
                myFan  =  F;
        }
        public void execute( ) {
                myFan . stopRotate( );
        }
}
public class TestCommand {
                public static void main(String[] args) {
                        Light  testLight = new Light( );
                        LightOnCommand testLOC = new LightOnCommand(testLight);
                        LightOffCommand testLFC = new LightOffCommand(testLight);
                        Switch testSwitch = new Switch(testLOC,testLFC);      
                        testSwitch.flipUp( );
                        testSwitch.flipDown( );
                        Fan testFan = new Fan( );
                        FanOnCommand foc = new FanOnCommand(testFan);
                        FanOffCommand ffc = new FanOffCommand(testFan);
                        Switch ts = new Switch( foc,ffc);
                        ts.flipUp( );
                        ts.flipDown( );
                }
}              

Command.java
public interface Command {
        public abstract void execute ( );
}

在上面的示例代码中,Command模式将 "调用操作的对象" (Switch)和 "知道如何执行操作的对象" (Light和Fan)完全分离开来。这带来了很大的灵活性:发送请求的对象只需要知道如何发送;它不必知道如何完成请求。

Command模式实现Transaction
Command模式也被称为action(动作)模式或transaction(事务)模式。假设有一个服务器,它接收并处理客户通过TCP/IP socket连接发送的transaction。这些transaction包含一个命令,后跟零个或多个 参数。

一些设计者可能会使用switch语句,每个command对应一个case。在一个面向对象工程的设计中,代码中如果使用switch语句,往往表示这是一个糟糕的设计。Command模式展现的是支持transaction的面向对象的方法,它可以用于解决这类设计问题。

在TestTransactionCommand.java程序的客户代码中,所有请求都被封装在通用的TransactionCommand对象中。TransactionCommand对象由客户创建并用CommandManager进行登记。等待的请求可以通过调用runCommands()在不同时期被执行,这带来了很大的灵活性。而且我们还可以将多个command组装成一个复合command。示例代码中还有CommandArgument,CommandReceiver,CommandManager这些类,以及TransactionCommand的子类--AddCommand和SubtractCommand。下面是对这些类的介绍。

· CommandArgument是一个helper类,它保存命令的参数。如果是大量(或可变数量)的任何类型的参数,它可以被重写,以简化参数的传递工作。

· CommandReceiver实现所有的命令处理方法(command-processing method),它用Singleton模式来实现。

· CommandManager是调用者,和前面例子中的Switch相当。它在其私有myCommand变量中保存通用TransactionCommand对象。runCommands()被调用时,它调用合适的TransactionCommand对象的execute()。

Java中,可以根据一个包含类名的字符串查找类的定义。在TransactionCommand类的execute ()操作中,我先计算出类名,然后将它链接到运行系统中--也就是说,类是根据需要被即时载入的。这里所采用的命名方式是,在命令名后连接一个 "Command" 字符串作为transaction command子类名,这样它就可以被动态载入。

注意,newInstance()返回的Class对象必须被转换为合适的类型。这意味着新的类要么必须实现一个接口,要么继承一个在编译期就为程序所知道的现有的类。本例中我们是实现Command接口,所以不存在问题。
file://TestTransactionCommand.java
import java.util.*;

final class CommandReceiver {
  private int[] c;

  private CommandArgument a;

     private CommandReceiver(){

       c = new int[2];

     }
     private static CommandReceiver cr = new CommandReceiver();
     public static CommandReceiver getHandle() {
return cr;

     }
     public void setCommandArgument(CommandArgument a) {
this.a = a;

     }
     public void methAdd() {
c = a.getArguments();

     System.out.println("The result is " + (c[0]+c[1]));

     }
     public void methSubtract() {
c = a.getArguments();

     System.out.println("The result is " + (c[0]-c[1]));

     }
}
class CommandManager {
   private Command myCommand;
   public CommandManager(Command  myCommand) {

     this.myCommand  =  myCommand ;   

   }
   public void runCommands( ) {

         myCommand.execute();    

   }
}

class TransactionCommand implements Command {
  private CommandReceiver commandreceiver;

  private Vector commandnamelist,commandargumentlist;

  private String commandname;

  private CommandArgument commandargument;

  private Command command;
  public TransactionCommand () {
this(null,null);

  }
  public TransactionCommand ( Vector  commandnamelist, Vector
commandargumentlist){

    this.commandnamelist = commandnamelist;

    this.commandargumentlist = commandargumentlist;

    commandreceiver =  CommandReceiver.getHandle(); 

  }
  public void execute( ) {
    for (int i = 0; i < commandnamelist.size(); i++) {
      commandname = (String)(commandnamelist.get(i));

      commandargument = (CommandArgument)((commandargumentlist.get(i)));

      commandreceiver.setCommandArgument(commandargument);

      String classname = commandname + "Command";
         try {

           Class cls = Class.forName(classname);

           command = (Command) cls.newInstance();

         }

         catch (Throwable e) {  

                  System.err.println(e);

         }

      command.execute();

    }

  }
}
class AddCommand extends TransactionCommand {

   private CommandReceiver cr;
   public AddCommand () {

      cr = CommandReceiver.getHandle(); 

   } 
   public void execute( ) { 

     cr.methAdd(); 

   }  

}
class SubtractCommand extends TransactionCommand {

   private CommandReceiver cr;
   public SubtractCommand () {

      cr = CommandReceiver.getHandle(); 

   }
   public void execute( ) {

     cr.methSubtract();

   }  

}

class CommandArgument {

   private int[] args;
   CommandArgument() {

     args = new int[2];

   }

   public int[] getArguments() {
return args;

   }

   public void setArgument(int i1, int i2) {

         args[0] = i1; args[1] = i2;

   }

}
public class TestTransactionCommand {

   private  Vector clist,alist;
   public TestTransactionCommand() {
clist = new Vector();

       alist = new Vector();

   }
   public void clearBuffer(Vector c, Vector a) {
clist.removeAll(c);

       alist.removeAll(a);

   }
   public Vector getClist() {
return clist;

   }
   public Vector getAlist() {
return alist;

   }
    public static void main(String[] args) {

       CommandArgument ca,ca2;
     TestTransactionCommand t = new TestTransactionCommand();
     ca = new CommandArgument();

     ca.setArgument(2,8);

     Vector myclist = t.getClist();

     Vector myalist = t.getAlist();

     myclist.addElement("Add"); myalist.addElement(ca);
     TransactionCommand tc = new TransactionCommand(myclist,myalist);

     CommandManager cm = new CommandManager(tc);      

                    cm.runCommands();
     t.clearBuffer(myclist,myalist);

     ca2 = new CommandArgument();

     ca2.setArgument(5,7);

     myclist = t.getClist();

     myalist = t.getAlist();

     myclist.addElement("Subtract"); myalist.addElement(ca2);

     myclist.addElement("Add"); myalist.addElement(ca2);
     TransactionCommand tc2 = new TransactionCommand(myclist,myalist);       

     CommandManager cm2 = new CommandManager(tc2);      

                    cm2.runCommands();
   }
}              

命令及其参数保存在列表中,并被封装成通用TransactionCommand对象。通用TransactionCommand用CommandManager来注册。任何时候,命令可以在CommandManager类中通过调用runCommands()接口来执行。

客户代码不依赖于任何具体的TransactionCommand子类,也就是说,我的设计是针对接口而不是实现。这带来了灵活性:要想增加一个新的命令,只需要定义一个新的TransactionCommand子类,并在CommandReceiver类中提供新的命令处理方法的实现。仅此而已。

结论
Command模式具有以下优点:

1. command将 "进行操作请求" 的对象和 "知道如何执行操作" 的对象分离开来(即,解耦)。

2. command是个很棒的对象。它可以象任何其它对象一样被使用和继承。

3. 多个command可以被组装成一个复合command。

4. 很容易增加新的command,因为不需要修改现有的类。

如果执行过的命令序列被保存在一个历史列表中,就可以遍历这个列表来提供undo和redo操作。要想实现这一功能,必须在Command接口中有一个unexecute()操作。这一练习留给读者自己去完成。

---------------------------------------------------------------------------

相关资源
· Design Patterns by Gamma, Helm, Johnson, Vlissides, Addison-Wesley, 1994, ISBN 0-201-63361-2 http://www.bookbuyer.com/cgi-bin/getTitle.cgi?ISBN=0201633612

· Dr. Dobb's Journal, January 1998: "Java Reflection: Not just for tool developers," by Paul Tremblett http://www.ddj.com/articles/1998/9801/9801c/9801c.htm

· Sun's Reflection page
http://java.sun.com/docs/books/tutorial/reflect/index.html

· "The Java Language Environment -- A White Paper" (May 1996), by James Gosling and Henry McGilton covers details about Java's dynamic loading and binding mechanism
http://java.sun.com/docs/white/langenv/
For more on taking advantage of Java's unique feature of dynamic loading and binding mechanism to build a dynamic and dynamically-extensible system, see
http://java.sun.com/docs/white/langenv/

SAP_MM_配额安排_PA认证总结 配额安排是企业进行供应商管理的一种方式。通过配额管理,企业可以与多家供应商保持业务往来,以保证某些紧缺原材料的正常供货。此外,企业也可以通过不同的配额比例,提高供应商优化服务、降低价格的积极性。 阅读详情

相关推荐

FPGA驱动OV5640:从SCCB协议到图像数据采集的实战解析

本文详细解析了使用FPGA驱动OV5640摄像头模组的完整流程,从SCCB协议通信、寄存器配置到图像数据采集。重点阐述了SCCB(与I2C类似)协议的实现细节、关键的上电复位时序,以及如何通过状态机解析视频流时序并捕获图像数据,为嵌入式视觉开发提供了实战指南。

weixin_29191761的博客 188

Java设计模式 -16- 命令模式(Command 模式)

Java设计模式 -16- 命令模式(Command 模式)前言命令模式的定义与特点优点:缺点:命令模式的结构与实现1. 模式的结构2. 模式的实现命令模式的应用实例命令模式的应用场景命令模式的扩展 前言 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满

Android系统工程师--小馬佩德罗 1521

【数电课程设计】---出租车计价器

文章目录1、任务要求2、方案3、收获 1、任务要求 2、方案 3、收获

LZY 1万+

命令模式(Command) Java实现

命令模式 命令模式(Command)的定义 命令模式属于对象的行为模式。命令模式又称为行动(Action)模式或交易(Transaction)模式。 命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。 命令模式的结构 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的...

CmdSmith的博客 1973

PointNetLK实战:5步搞定点云配准(附ModelNet40数据集训练技巧)

本文提供了一份详细的PointNetLK实战指南,帮助读者在5步内掌握点云配准技术。文章以ModelNet40数据集为例,深入讲解了环境搭建、数据预处理、模型训练与调试等核心步骤,并分享了关键的训练技巧和调参策略,旨在让开发者快速实现并应用这一高效的深度学习配准方法。

wind6的博客 462

Etcd教程 — 第三章 Etcd集群动态发现、DNS发现

Etcd教程 — 第三章 Etcd集群动态发现、DNS发现

Mr_XiMu的博客 2825

设计模式-命令模式(Command)

关注公众号 JavaStorm 获取更多成长。 大约需要6分钟读完。建议收藏后阅读。 命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。 GitHub地址: https://github.com/UniqueDong/zero-design-stu 中的 headfirst 包下代码。 概述 命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。 每一个命令都是...

深蓝旭的博客 2736

IEEE 754浮点数与十六进制转换:从原理到实战避坑指南

在计算机系统中,数据的二进制表示与内存布局是底层开发的核心基础。IEEE 754标准定义了浮点数在内存中的精确格式,包括符号位、指数位和尾数位的分工,以及零、无穷大和NaN等特殊值的编码。理解这一原理对于处理原始字节流至关重要,尤其是在涉及跨平台或跨设备通信时。其技术价值在于,它能帮助开发者从根本上解决数据解析错误、通信协议不一致以及程序调试中的“灵异”问题。在嵌入式开发、网络通信(如Modbus协议)和固件解析等应用场景中,浮点数与十六进制的转换是高频操作。然而,字节序(大端/小端)是转换过程中最常见的“

weixin_33835103的博客 430

java 命令设计模式_java设计模式-Command(命令)模式

Command定义将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。优点: 解耦了调用者和接受者之间联系。调用者调用一个操作,接受者接受请求执行相应的动作,因为使用Command模式解耦,调用者无需知道接受者任何接口。缺点: 造成出现过多的具体命令类代码例子如下:播放器执行命令者:package command;//命令执行者播放器pub...

weixin_39760689的博客 226

YOLO详解

本文参考知乎 https://zhuanlan.zhihu.com/p/25236464 1. YOLO的创新点 YOLO将物体检测作为回归问题求解。基于一个单独的end-to-end网络,完成从原始图像的输入到物体位置和类别的输出。 从网络设计上,YOLO与two steps的目标检测方法如RCNN、Fast RCNN和Faster RCNN的区别如下: YOLO训练和检测均是在一个单独网...

UnknownPlayer的博客 9959

hive sql每个用户的累积访问次数

我们有如下的用户访问数据 userId visitDate visitCount u01 2017/1/21 5 u02 2017/1/23 6 u03 2017/1/22 8 u04 2017/1/20 3 u01 2017/1/23 6 u01 2017/2/21 8 U02 2017/1/23 6 U01 2017/2/22 4 要求使用SQL...

weixin_39150719的博客 3487

命令模式(Command)

意图:将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

QQ657205470的博客 1569

用 CL_ABAP_PARALLEL 把批量处理跑进并行对话进程:资源配额、超时治理与可复制的落地模板

文章摘要: CL_ABAP_PARALLEL是SAP推荐的并行处理工具,适用于时间窗口受限的批量任务处理。它基于aRFC/pRFC机制,通过对话进程实现并行,能将小时级任务压缩到分钟级。使用时需注意版本兼容性(可能需要Note 2791374)、资源限制(会话数、进程数)和任务切片策略。提供两种实现方式:继承式(重定义do方法)和接口式(实现IF_ABAP_PARALLEL)。关键参数包括并发控制(p_percentage)、超时设置(p_timeout)和调试开关(p_debug)。最佳实践建议按业务维度

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 244

Java Tip: 实现Command模式 (转)

Java Tip: 实现Command模式 (转)[@more@] Java Tip: 实现Command模式 概述有时需要向对象发送请求,但是不知道 "被请求的操作" 或 "请求的接受者" 的任何信息。在面向过程的程序设...

csd3176的博客 113

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

开发模式:实现Command模式

google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//<script type="text/java

java专栏 544

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

实现Command模式

概述有时需要向对象发送请求,但是不知道 "被请求的操作" 或 "请求的接受者" 的任何信息。在面向过程的程序设计语言中,这类通信是通过回调函数来完成的:在某个地方登记这个函数,然后在后面调用它。在面向对象程序中,command(命令)与回调函数等价,它封装了回调函数。本文演示如何在Java中实现Command模式。------------------------------------------

p0303230的专栏 651

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Command: analyze-performance

Analyze the performance of the file specified in $ARGUMENTS. ## Steps: 1. Read the file at path: $ARGUMENTS 2. Identify performance bottlenecks 3. Suggest optimizations 4. Create a benchmark script `

gitblog_00167的博客 976

用 DB4S 管本地 SQLite:从安装到改数据的 5 步实操

你想直观地改一条本地 SQLite 数据库里的记录,命令行太啰嗦,搭一个网页后台又不值当。DB Browser for SQLite(DB4S)是一个免费开源的 SQLite 数据库管理工具:打开数据库文件就能浏览、改数据、建表,不需要写复杂的 SQL。下面从安装讲起,实测一遍完整流程。 ## 📦 环境准备:DB Browser for SQLite 安装步骤 - Windows: ```

gitblog_00743的博客 151

KMS_VL_ALL_AIO 激活脚本使用指南:Windows 与 Office 一键 KMS 激活

KMS_VL_ALL_AIO 是一个在本地运行的 KMS 激活脚本,把 Windows 与 Office 的批量激活合并进一个带菜单的 `.cmd` 文件里。你不用记一堆 `slmgr` 参数,也不用按版本逐个试密钥——它会自动识别系统与已安装的 Office 组件,走对应的激活分支,还能顺手装一个自动续期任务。本文按"先跑通、再按需微调"的顺序讲用法。 ## 🧭 装机或批量部署时,它替你省掉

gitblog_00897的博客 228

Docker快速上手

本篇文章不再赘述Docker的出身、优缺点、理念等一些概念,想要了解的可以去网上自行查阅资料,几乎每篇相关文章都会有的 - -#

m0_57697768的博客 1597

Lithe-IDEA:基于Rust+WASM的轻量开源Java IDE

IDE(集成开发环境)是Java开发者日常编码的核心工具,其本质是代码编辑、智能分析与构建运行的协同系统。传统IDE依赖JVM运行时,导致启动慢、内存高、定制难;而现代轻量IDE正通过架构解耦实现突破——将前端渲染、语言服务(LSP)、构建执行分离,以WebAssembly替代Electron,用Rust重写核心逻辑,实现零JVM依赖。这种设计不仅显著降低资源占用,更天然适配云原生与容器化工作流,支撑Spring Boot等主流框架的高效开发。Lithe-IDEA正是这一范式的典型代表,它将Java开发体验

weixin_33827590的博客 299

Goose 高效使用实战:6 条提升 AI Agent 协作效率的核心技巧(附仓库源码佐证)

本文源自 goose 官方博客 "6 Essential Tips for Working with goose",并结合当前仓库源码与配套文档进行深度扩充。无论你是用 goose 写代码、做自动化还是管理复杂项目,文中 6 条实践经验——保持会话聚焦、精简扩展、善用 `.goosehints`、选对权限模式、分步执行与迭代精炼——都能直接帮助你获得更准确、更省资源的使用效果。读完本文,你将不仅理

gitblog_00860的博客 332

Arthas line 命令实战指南:在指定源码行精确观测方法内部状态

本文是 Arthas(Alibaba Java Diagnostic Tool)`line` 命令的完整实战指南。`line` 是 Arthas 提供的"行级观测"命令,能够在目标方法的**指定源码行**插入探针,当执行流到达该行时输出当前线程、耗时、行号以及 OGNL 表达式计算结果,特别适合排查"方法内部某一行变量值不符合预期"这类问题。读完本文,你将掌握 `line` 的全部参数语义、表达式

gitblog_00561的博客 396

Arthas sysprop 命令详解:查看与动态修改 JVM 系统属性

> 本文以 Arthas 官方英文文档 [sysprop 命令参考](https://link.gitcode.com/i/3a6fac1038b59b513ed33dd416925a5f) 为主线,结合仓库源码([SystemPropertyCommand.java](https://link.gitcode.com/i/94bf6bb4d2f38571a357f34e05be4a09))与相关

gitblog_00470的博客 338

C++ Win32系统托盘程序开发:从Shell_NotifyIcon到消息循环实战

在Windows桌面开发中,系统托盘是后台服务与工具软件常驻系统的重要界面组件。其核心原理基于Windows的消息驱动机制,通过Shell_NotifyIcon API与系统Shell进行通信,将图标注册到任务栏通知区域。技术实现关键在于正确处理NOTIFYICONDATA结构体版本、绑定隐藏窗口的消息循环以及自定义消息处理。掌握这些底层机制不仅能实现高度定制化的托盘功能,如动态图标更新和复杂右键菜单,更能深入理解Windows GUI编程的消息处理与资源管理逻辑。本文通过纯C++和Win32 API实战,

weixin_33850890的博客 371

Apache SkyWalking 线程 Dump 合并机制:从快照到栈树的性能剖析原理与调试实践

Apache SkyWalking 的性能剖析(profiling)是一个面向生产环境的增强功能:它通过周期性抓取线程 dump(thread dump)来估算方法的执行时间,而不是在代码中插入大量 local span,因此资源开销远低于分布式追踪式的慢方法定位。本文围绕 SkyWalking 官方文档《Thread dump merging mechanism》展开,结合 OAP Server

gitblog_01133的博客 936
上一篇: Java Q&A: 使用Singleton模式?给我一个理由先!
下一篇: 基于DirectDraw的Gamma calibrator机制之探讨
lostmouse
博客等级 码龄26年 22粉丝 63原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值