作为一名热爱分享技术见解的程序员,我经常思考一个问题:为什么有些代码能优雅地应对变化,而有些代码却随着需求迭代变得越来越臃肿?今天,我想和大家聊聊那些比设计模式更基础、更重要的东西——设计原则。
记得我刚入行时,也曾痴迷于学习各种设计模式,把《设计模式》这本书翻得卷了边。但后来我发现,很多同事(包括曾经的我)犯了一个通病:为了模式而模式。我们生搬硬套各种模式,却忽略了背后的原则,结果代码看起来"高大上",实则混乱不堪。
设计原则才是设计模式的根基。就像武侠小说中的内功心法,模式是招式,原则是内功。没有内功支撑的招式,不过是花拳绣腿罢了。
我的理解:就像人一样,一个类也应该"术业有专攻"。
常见误区:
优化建议:
# 不好的写法
class UserService:
def login(self): ...
def update_profile(self): ...
def calculate_points(self): ...
# 好的写法
class LoginService: ...
class UserProfileService: ...
class UserPointService: ...
经验分享:我曾经重构过一个3000多行的Service类,拆分成5个小类后,不仅代码更清晰,团队协作也更顺畅了。
我的感悟:好的代码应该像乐高积木,通过添加新模块来扩展,而不是拆了重建。
反例警示:
优雅方案:
实战心得:在我的支付系统重构中,采用策略模式后,新增支付方式的开发时间从2天缩短到2小时。
我的教训:曾经因为违反这个原则,导致线上事故...
错误示范:
class User:
def view_page(self):
print("查看普通页面")
class NormalUser(User):
def view_page(self):
raise PermissionError("无权访问") # 违反LSP!
正确姿势:
总结:子类不应该破坏父类的契约,权限控制应该通过其他方式实现。
我的觉醒时刻:曾经维护过一个"肥胖接口",让我苦不堪言...
问题代码:
痛点分析:
重构方案:
项目收获:在一个消息中心重构项目中,通过接口隔离,我们的单元测试覆盖率从60%提升到了85%,因为每个接口的职责更加明确单一了。
我的深刻教训:曾经因为高层模块直接依赖底层实现,导致一次痛苦的系统迁移...
问题代码:
遇到的情况:
改进方案:
架构感悟:自从采用依赖倒置后,我们的系统模块化程度显著提高,不同环境的配置切换变得轻而易举。
我的调试噩梦:曾经因为过度暴露内部细节,导致一次线上事故...
问题代码:
暴露的问题:
重构方案:
性能优化案例:后来我们需要给保存操作添加Redis缓存,得益于迪米特法则,只需修改Repository实现,所有业务代码都不受影响。
通过多年的项目实践,我总结出这些原则与常见模式的对应关系:
好的代码 = 正确的原则 + 恰当的模式
原则是指导思想,模式是具体实现。就像:
设计原则 | 体现该原则的模式 |
---|---|
单一职责 | 装饰者模式、外观模式 |
开闭原则 | 策略模式、观察者模式 |
里氏替换 | 模板方法模式 |
接口隔离 | 适配器模式 |
依赖倒置 | 依赖注入、工厂模式 |
迪米特法则 | 门面模式、中介者模式 |
记得Martin Fowler说过:"任何傻瓜都能写出计算机能理解的代码,唯有优秀的程序员才能写出人类能理解的代码。"设计原则正是为了帮助我们写出人类友好的代码。
终极建议:下次当你准备使用设计模式时,先问问自己:我想要解决什么原则性问题?这样的思考方式会让你的代码质量产生质的飞跃。
编程感悟:设计原则就像编程界的"道",而模式是"术"。只有悟透原则,才能真正写出优雅、健壮的代码。、
如果你觉得这个系列有帮助,欢迎收藏转发。也欢迎在评论区分享你在实践中应用设计原则的故事!
# 这种写法每加一种支付方式就要修改代码
def process_payment(pay_type):
if pay_type == "WECHAT":
print("处理微信支付")
# 微信支付逻辑...
elif pay_type == "ALIPAY":
print("处理支付宝支付")
# 支付宝支付逻辑...
else:
raise ValueError("不支持的支付方式")
# 使用示例
process_payment("WECHAT") # 处理微信支付
from abc import ABC, abstractmethod
# 策略接口
class PayStrategy(ABC):
@abstractmethod
def pay(self): pass
# 具体策略
class WechatPay(PayStrategy):
def pay(self): print("微信支付")
class Alipay(PayStrategy):
def pay(self): print("支付宝支付")
# 使用
def process_payment(strategy: PayStrategy):
strategy.pay()
# 新增支付方式只需添加新类
class ApplePay(PayStrategy):
def pay(self): print("Apple Pay")
from abc import ABC, abstractmethod
class AbstractUser(ABC):
@abstractmethod
def access(self): pass
class NormalUser(AbstractUser):
def access(self): print("普通用户访问")
class AdminUser(AbstractUser):
def access(self):
print("管理员访问")
print("执行管理员特权操作")
class NotificationService:
def send_email(self): ...
def send_sms(self): ...
def send_push(self): ...
class EmailNotification:
def send_email(self): ...
class SmsNotification:
def send_sms(self): ...
class PushNotification:
def send_push(self): ...
class SmsNotification:
def send(self, message):
print(f"[短信] {message}")
class OrderService:
def __init__(self):
self.notifier = SmsNotification() # 直接实例化具体类
def create_order(self):
print("创建订单业务逻辑...")
self.notifier.send("订单创建成功")
# 使用
service = OrderService()
service.create_order()
from abc import ABC, abstractmethod
# 1. 定义抽象(高层模块不应依赖低层模块,二者都应依赖抽象)
class NotificationService(ABC): # 抽象接口
@abstractmethod
def send(self, message: str) -> None:
pass
# 2. 具体实现(低层模块依赖抽象)
class SmsNotification(NotificationService):
def send(self, message):
print(f"[短信] {message}")
class EmailNotification(NotificationService):
def send(self, message):
print(f"[邮件] {message}")
# 3. 业务类通过依赖注入使用抽象(高层模块依赖抽象)
class OrderService:
def __init__(self, notifier: NotificationService): # 依赖注入
self.notifier = notifier
def create_order(self):
print("创建订单业务逻辑...")
self.notifier.send("订单创建成功")
# 使用示例
if __name__ == "__main__":
# 可以灵活切换通知方式
sms_service = OrderService(SmsNotification())
sms_service.create_order() # 输出: [短信] 订单创建成功
email_service = OrderService(EmailNotification())
email_service.create_order() # 输出: [邮件] 订单创建成功
# 单元测试时可以轻松注入Mock
class MockNotification(NotificationService):
def send(self, message):
print(f"[测试] {message}")
test_service = OrderService(MockNotification())
test_service.create_order() # 输出: [测试] 订单创建成功
class UserService:
def register(self, user):
# 直接操作数据库细节
conn = psycopg2.connect("dbname=test user=postgres")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO users (name, email) VALUES (%s, %s)",
(user.name, user.email)
)
conn.commit()
# 还有更多直接操作数据库的代码...
class UserRepository:
def __init__(self):
self.conn = psycopg2.connect("dbname=test user=postgres")
def save(self, user):
cursor = self.conn.cursor()
cursor.execute(
"INSERT INTO users (name, email) VALUES (%s, %s)",
(user.name, user.email)
)
self.conn.commit()
class UserService:
def __init__(self):
self.repo = UserRepository()
def register(self, user):
# 只关注业务逻辑
self.repo.save(user)
# 可以在这里添加其他业务逻辑...