设计模式是解决在软件设计中经常遇到的一类问题的最佳实践。使用设计模式有助于设计出可重用、可维护、可扩展且灵活的软件系统。在设计模式中,有一些重要的原则,这些原则指导我们如何编写出高质量、易于维护的代码。
以下是设计模式中的几大原则,以及对应的 Java 代码示例:
一个类应该只有一个引起变化的原因。
示例:
// 违反了单一职责原则
public class UserManager {
public void createUser(User user) {
// 创建用户的逻辑
}
public void deleteUser(int userId) {
// 删除用户的逻辑
}
public void sendEmail(User user) {
// 发送邮件的逻辑
}
}
// 遵循单一职责原则
public class UserService {
public void createUser(User user) {
// 创建用户的逻辑
}
public void deleteUser(int userId) {
// 删除用户的逻辑
}
}
public class EmailService {
public void sendEmail(User user) {
// 发送邮件的逻辑
}
}
软件实体(类、模块、函数等)应该是可扩展的,但是不可修改的。
示例:
// 假设有一个图形接口和几个实现类
interface Shape {
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Circle...");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing Rectangle...");
}
}
// 遵循开放封闭原则的图形工厂
public class ShapeFactory {
public Shape getShape(String shapeType) {
if ("CIRCLE".equalsIgnoreCase(shapeType)) {
return new Circle();
} else if ("RECTANGLE".equalsIgnoreCase(shapeType)) {
return new Rectangle();
}
// 更多的图形类型可以在不修改此工厂类的情况下添加
return null;
}
}
子类必须能够替换其父类,并且替换后,软件的行为要保持不变。
示例:
class Bird {
void fly() {
System.out.println("Bird is flying...");
}
}
class Ostrich extends Bird {
@Override
void fly() {
throw new UnsupportedOperationException("Ostriches can't fly");
}
}
// 使用 Bird 的客户端代码
public class Test {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly(); // 输出 "Bird is flying..."
// 假设我们错误地将 Ostrich 实例当作 Bird 来使用
Bird ostrich = new Ostrich();
ostrich.fly(); // 抛出异常,违反了里氏替换原则
}
}
在这个示例中,Ostrich 类不应该继承自 Bird 类,因为 Ostrich 不能飞。
客户端不应该被强制依赖于它们不使用的接口。
示例:
// 违反了接口隔离原则
interface Machine {
void start();
void stop();
void print();
void scan();
}
class MultifunctionPrinter implements Machine {
// 实现所有方法,包括它不需要的 scan 方法
}
// 遵循接口隔离原则
interface Printable {
void print();
}
interface Scannable {
void scan();
}
interface Machine {
void start();
void stop();
}
class MultifunctionPrinter implements Printable, Scannable {
@Override
public void print() {
// 实现打印逻辑
}
@Override
public void scan() {
// 实现扫描逻辑
}
}
要依赖于抽象,不要依赖于具体。
示例:
// 违反了依赖倒置原则
class HighLevelModule {
LowLevelModule lowLevelModule = new LowLevelModule();
public void doSomething()