Applying the Open‑Closed Principle and Bitmask Design for Extensible System Architecture
The article explains the six SOLID design principles, emphasizes the importance of the Open‑Closed principle, and demonstrates how to achieve extensible database schemas and APIs using type fields, extendable JSON columns, bitmap role encoding, and strategy/template patterns with concrete Java code examples.
Six Design Principles
The author lists the six SOLID principles—Single Responsibility, Liskov Substitution, Dependency Inversion, Interface Segregation, Law of Demeter, and Open‑Closed—stating that the Open‑Closed principle is the most important because it underpins system extensibility.
Database Dimension
Design Type Fields
Add two columns biz_type and biz_sub_type to isolate large business categories and sub‑categories, allowing future expansion without schema changes.
Design Extend Fields
Add three nullable columns extend1 , extend2 , extend3 to store JSON‑encoded flexible data such as order, product, or marketing extensions.
Design Business Binary Field
Introduce a user_flag column that stores role information as a bitmap, enabling multiple roles per user with a single integer value.
id
name
super
admin
normal
101
用户一
1
0
0
102
用户二
0
1
0
103
用户三
0
0
1
104
用户四
1
1
1
Using a bitmap, the same data can be represented as decimal values 4, 2, 1, and 7 respectively.
Solution – Bitmap Method
Define each role as a single bit (1, 2, 4) and store the combined value in user_flag . The following Java enum shows the bit‑shift definition:
/**
* User role enumeration
*/
public enum UserRoleEnum {
// 1 -> 00000001
NORMAL(1, "普通用户"),
// 2 -> 00000010
MANAGER(1 << 1, "管理员"),
// 4 -> 00000100
SUPER(1 << 2, "超级管理员");
private int code;
private String description;
private UserRoleEnum(int code, String description) {
this.code = code;
this.description = description;
}
public String getDescription() { return description; }
public int getCode() { return code; }
}Utility methods for adding, removing, and checking roles use bitwise OR, XOR, and AND operations respectively:
public static Integer addRole(Integer oldRole, Integer addRole) {
return oldRole | addRole;
}
public static Integer removeRole(Integer oldRole, Integer delRole) {
return oldRole ^ delRole;
}
public static boolean hasRole(Integer allRole, Integer qryRole) {
return (allRole & qryRole) == qryRole;
}SQL examples show how to query users with a specific role using the bitmap column.
Interface Dimension
Design Typed Parameters
Use explicit fields such as bizType and bizSubType in DTOs to match the database type columns.
Design Loose Parameters
Alternatively, use a Map for flexible, loosely‑typed parameters.
Design API Versioning
Expose versioned URLs like /order/1.0/createOrder and /order/1.1/createOrder so old and new versions can coexist.
Vertical and Horizontal Design
Vertical dimension separates strategies (discount, logistics, refund) using the Strategy pattern. Horizontal dimension composes these strategies per order type using the Template Method pattern.
Strategy Interfaces and Implementations
public interface DiscountStrategy { void discount(OrderBO orderBO); }
@Component public class TypeADiscountStrategy implements DiscountStrategy { public void discount(OrderBO o){ o.setPrice(o.getPrice()*0.9); } }
@Component public class TypeBDiscountStrategy implements DiscountStrategy { public void discount(OrderBO o){ o.setPrice(o.getPrice()*0.8); } }
@Component public class TypeCDiscountStrategy implements DiscountStrategy { public void discount(OrderBO o){ o.setPrice(o.getPrice()*0.7); } }A factory registers each strategy by order type code, and an executor retrieves and runs the appropriate strategy.
Template Method for Order Creation
public abstract class AbstractCreateOrderFlow {
public void createOrder(OrderBO orderBO) {
// validation
// discount
discount(orderBO);
// weighing
weighing(orderBO);
// refund support
supportRefund(orderBO);
// persist
}
protected abstract void discount(OrderBO orderBO);
protected abstract void weighing(OrderBO orderBO);
protected abstract void supportRefund(OrderBO orderBO);
}The concrete CreateOrderFlow injects executors for each step and delegates the work.
Conclusion
The article presents seven concrete techniques—type fields, extend fields, bitmap fields, typed parameters, loose parameters, API versioning, and vertical/horizontal design—to improve system extensibility.
Final Note
The author encourages readers to like, share, and follow the public account for more technical content.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.