Última actividad 10 months ago

Python Mixin 設計模式允許類別透過多重繼承增加功能,如日誌、權限管理、事件驅動、異常處理與審計,提升可維護性與擴展性,適用於模組化應用開發。

timmy revisó este gist 10 months ago. Ir a la revisión

1 file changed, 145 insertions

user_with_logging_and_permissions.py(archivo creado)

@@ -0,0 +1,145 @@
1 + import datetime
2 + import json
3 + import threading
4 + import traceback
5 +
6 + class LoggingMixin:
7 + def __init__(self, log_to_file=False, log_file="app.log", *args, **kwargs):
8 + self.log_to_file = log_to_file
9 + self.log_file = log_file
10 + super().__init__(*args, **kwargs)
11 +
12 + def log(self, message):
13 + timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
14 + log_message = f"[{timestamp}] {self.__class__.__name__}: {message}"
15 + if self.log_to_file:
16 + with open(self.log_file, "a") as f:
17 + f.write(log_message + "\n")
18 + else:
19 + print(log_message)
20 +
21 + class TimestampMixin:
22 + def __init__(self, *args, **kwargs):
23 + self.created_at = datetime.datetime.now().isoformat()
24 + self.updated_at = self.created_at
25 + super().__init__(*args, **kwargs)
26 +
27 + def update_timestamp(self):
28 + self.updated_at = datetime.datetime.now().isoformat()
29 + self.log(f"更新時間標記: {self.updated_at}")
30 +
31 + class DatabaseMixin:
32 + _database = {}
33 +
34 + def save(self):
35 + DatabaseMixin._database[self.name] = json.dumps(self.__dict__, default=str)
36 + self.log(f"資料已儲存: {self.name}")
37 +
38 + @classmethod
39 + def get(cls, name):
40 + data = cls._database.get(name, None)
41 + return json.loads(data) if data else None
42 +
43 + class PermissionMixin:
44 + _roles_permissions = {
45 + "admin": ["create", "read", "update", "delete"],
46 + "editor": ["create", "read", "update"],
47 + "viewer": ["read"]
48 + }
49 +
50 + def __init__(self, role="viewer", *args, **kwargs):
51 + self.role = role
52 + self.permissions = self._roles_permissions.get(role, [])
53 + super().__init__(*args, **kwargs)
54 +
55 + def has_permission(self, perm):
56 + return perm in self.permissions
57 +
58 + def change_role(self, new_role):
59 + self.role = new_role
60 + self.permissions = self._roles_permissions.get(new_role, [])
61 + self.log(f"角色變更為 {new_role},新權限: {self.permissions}")
62 +
63 + class EventMixin:
64 + _events = {}
65 +
66 + @classmethod
67 + def on(cls, event_name, callback, async_mode=False):
68 + if event_name not in cls._events:
69 + cls._events[event_name] = []
70 + cls._events[event_name].append((callback, async_mode))
71 +
72 + @classmethod
73 + def trigger(cls, event_name, *args, **kwargs):
74 + if event_name in cls._events:
75 + for callback, async_mode in cls._events[event_name]:
76 + if async_mode:
77 + threading.Thread(target=callback, args=args, kwargs=kwargs).start()
78 + else:
79 + callback(*args, **kwargs)
80 +
81 + class ExceptionHandlingMixin:
82 + def handle_exception(self, func, *args, **kwargs):
83 + try:
84 + return func(*args, **kwargs)
85 + except Exception as e:
86 + self.log(f"發生異常: {e}")
87 + traceback.print_exc()
88 +
89 + class AuditMixin:
90 + _audit_log = []
91 +
92 + def audit(self, action, details):
93 + record = {
94 + "timestamp": datetime.datetime.now().isoformat(),
95 + "user": self.name,
96 + "action": action,
97 + "details": details
98 + }
99 + self._audit_log.append(record)
100 + self.log(f"審計記錄: {record}")
101 +
102 + class User(LoggingMixin, TimestampMixin, DatabaseMixin, PermissionMixin, EventMixin, ExceptionHandlingMixin, AuditMixin):
103 + def __init__(self, name, role="viewer", log_to_file=False):
104 + super().__init__(role=role, log_to_file=log_to_file)
105 + self.name = name
106 + self.log(f"User '{self.name}' 已建立,角色: {self.role}")
107 +
108 + def update_name(self, new_name):
109 + self.audit("update_name", {"old_name": self.name, "new_name": new_name})
110 + self.log(f"名稱從 '{self.name}' 變更為 '{new_name}'")
111 + old_name = self.name
112 + self.name = new_name
113 + self.update_timestamp()
114 + self.trigger("user_updated", old_name, new_name)
115 +
116 + # 測試範例
117 + if __name__ == "__main__":
118 + # 訂閱事件
119 + def on_user_updated(old_name, new_name):
120 + print(f"🔔 使用者名稱變更通知: {old_name} → {new_name}")
121 +
122 + User.on("user_updated", on_user_updated)
123 + User.on("user_updated", lambda o, n: print(f"📡 非同步通知: {o} → {n}"), async_mode=True)
124 +
125 + # 建立使用者
126 + user1 = User("Alice", role="editor", log_to_file=True)
127 + user1.save()
128 +
129 + # 更新名稱
130 + user1.update_name("Alice_Wonderland")
131 +
132 + # 檢查權限
133 + print(f"Alice 是否有 'read' 權限?{user1.has_permission('read')}")
134 + print(f"Alice 是否有 'delete' 權限?{user1.has_permission('delete')}")
135 +
136 + # 變更角色
137 + user1.change_role("admin")
138 +
139 + # 從資料庫取得使用者
140 + retrieved_user = User.get("Alice_Wonderland")
141 + if retrieved_user:
142 + print(f"從資料庫取得使用者: {retrieved_user}")
143 +
144 + # 測試異常處理
145 + user1.handle_exception(lambda: 1 / 0)
Siguiente Anterior