Beyond Singletons

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//* 1
namespace Helper {
void Function();
}

//* 2
class Helper {
public:
static void Function();
};

//* 3
class Helper : public Singleton<Helper> {
public:
void Function();
};

简单比较一下:

  1. 三种方式都可以实现全局访问,不需要实例化,接口实现中也可以使用 static 缓存数据(虽然不推荐)。
  2. 方式 1 中用命名空间隔离,调用起来跟方式 2 一样。方式 3 还得用 Singleton<Helper>::GetInstance() 来获取实例,显得有些繁琐。

我个人是推荐 1 的。这种方式简单明了,直接使用命名空间来组织全局函数,而且暴露的信息最少。
不喜欢 2 和 3 主要是因为引入了类的对象,但是又不能实例化多个实例,感觉有点多余。


Gemini Time

Of course. Here is a comparison of the three API designs you provided.

High-Level Overview

  1. namespace Helper: This approach uses a C++ namespace to group related functions. Function() is a free function logically contained within the
    Helper scope. This is a very common and idiomatic way to organize utility functions in C++.

  2. class Helper with static member: This design uses a class with a static member function. This also groups Function() under the Helper name, but
    within a class context. It’s similar to the namespace approach, as you don’t need an instance of the class to call the function.

  3. Singleton<Helper>: This approach uses the Singleton design pattern. It ensures that only one instance of the Helper class ever exists. The
    Function() is a regular member function that operates on this single instance, which allows it to manage state.

Recommendations

  • Use the namespace approach (1) for most cases. It is the cleanest, most testable, and most idiomatic C++ solution for organizing related utility functions that do not need to share state.

  • Consider the static class member approach (2) if the function is intrinsically tied to a class concept but doesn’t require an instance. However, a namespace is often still a better choice.

  • Use the Singleton pattern (3) with extreme caution. It should only be used when you have a clear and explicit requirement for a single, globally accessible object that manages a shared resource or state (e.g., a logger, a database connection pool). Be prepared for the challenges it introduces in testing and code maintainability. In many cases, Dependency Injection is a more flexible and testable alternative.

GH: Lazy Brush

Lazy Brush 是一个惰性的画笔。

lazy-brush


下面是 AI 时间:

The lazy-brush library implements a smooth drawing system based on three core ideas: lazy radius constraint, geometric movement calculation, and optional friction control.

Core Concepts

1. Lazy Radius Constraint

The fundamental principle is that the brush only moves when the pointer exceeds a defined radius distance 1 . This creates a “lazy area” where small pointer movements don’t affect the brush position, enabling smooth drawing without jitter.

一个跟踪区间,实现惰性

2. Two-Point System Architecture

The library maintains two coordinate points managed by the LazyPoint class 2 :

  • Pointer: tracks actual input device position
  • Brush: the drawing position that follows the pointer with constraints

分离触摸点和画笔点

3. Distance-Based Movement Algorithm

When the pointer moves outside the radius, the brush moves by exactly distance - radius pixels toward the pointer 3 . This ensures the brush maintains the radius distance from the pointer after movement.

保持画笔点和触摸点的距离

Wiki pages you might want to explore: