设计模式的七大原则——用例子和代码示例带你深刻了解!!

设计模式的七大原则是面向对象设计的核心,它们是创建高质量、可维护性代码的基石。以下是这七大原则及其概念和例子:

1. 单一职责原则 (Single Responsibility Principle, SRP)

概念:一个类应该只有一个变化的原因。这意味着一个类应该只包含与某个单一功能相关的代码。

例子:假设我们有一个 UserService 类,它负责用户注册和用户登录。如果有一天,我们想要添加一个新功能来更新用户信息,这时 UserService 类就需要修改,因为它负责的功能发生了变化。为了遵循SRP,我们应该将这个类拆分为两个:UserRegistrationServiceUserLoginService

// 不良设计,违反SRP
class UserService {
    public void registerUser(String username, String password) {
        // 注册用户逻辑
    }
    
    public void loginUser(String username, String password) {
        // 登录用户逻辑
    }
    
    public void updateUserInfo(String username, String newInfo) {
        // 更新用户信息逻辑
    }
}

// 遵循SRP的设计
class UserRegistrationService {
    public void registerUser(String username, String password) {
        // 注册用户逻辑
    }
}

class UserLoginService {
    public boolean loginUser(String username, String password) {
        // 登录用户逻辑
        return true; // 假设登录成功
    }
}

class UserUpdateService {
    public void updateUserInfo(String username, String newInfo) {
        // 更新用户信息逻辑
    }
}

2. 开闭原则 (Open/Closed Principle, OCP)

概念:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不修改现有代码的情况下,应该能扩展一个软件实体以添加新的功能。

例子:假设有一个 Shape 接口,它有一个 draw 方法。现在,我们有一个 Rectangle 类和 Circle 类实现了这个接口。如果我们想要添加一个新的形状 Triangle,我们应该通过扩展而不是修改现有类来实现。

// 遵循OCP的设计
abstract class Shape {
    public abstract void draw();
}

class Rectangle extends Shape {
    public void draw() {
        System.out.println("Drawing Rectangle");
    }
}

class Circle extends Shape {
    public void draw() {
        System.out.println("Drawing Circle");
    }
}

// 假设我们想要添加一个新的形状Triangle
class Triangle extends Shape {
    public void draw() {
        System.out.println("Drawing Triangle");
    }
}

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

概念:所有引用基类(父类)的地方都可以透明地使用其子类的对象。这意味着子类可以替换基类,而不会改变程序的行为。

例子:假设有一个 Animal 类,它有一个 move 方法。我们有一个子类 Dog,它覆盖了 move 方法。在任何使用 Animal 的地方,我们都可以使用 Dog,而程序的行为不会改变。

// 遵循LSP的设计
class Animal {
    public void move() {
        System.out.println("Animal is moving");
    }
}

class Dog extends Animal {
    public void move() {
        System.out.println("Dog is running");
    }
}

// LSP允许子类替换基类
class Zoo {
    public void animalMovement(Animal animal) {
        animal.move();
    }
}

public class Main {
    public static void main(String[] args) {
        Zoo zoo = new Zoo();
        Animal animal = new Dog();
        zoo.animalMovement(animal); // Dog is running
    }
}

4. 接口隔离原则 (Interface Segregation Principle, ISP)

概念:使用多个专门的接口比使用单一的总接口要好。这意味着接口应该小而精,只提供客户端实际需要的功能。

例子:假设有一个 Animal 类,它实现了 eatsleepmove 三个方法。如果我们有一个专门处理睡眠的类,它不需要 eatmove 方法,那么我们应该创建一个只包含 sleep 方法的接口。

// 遵循ISP的设计
interface EatBehavior {
    void eat();
}

interface SleepBehavior {
    void sleep();
}

interface Animal {
    EatBehavior getEatBehavior();
    SleepBehavior getSleepBehavior();
}

class Cat implements Animal {
    private EatBehavior eatBehavior;
    private SleepBehavior sleepBehavior;

    public Cat() {
        eatBehavior = new EatBehavior() {
            public void eat() {
                System.out.println("Cat is eating");
            }
        };
        sleepBehavior = new SleepBehavior() {
            public void sleep() {
                System.out.println("Cat is sleeping");
            }
        };
    }

    public EatBehavior getEatBehavior() {
        return eatBehavior;
    }

    public SleepBehavior getSleepBehavior() {
        return sleepBehavior;
    }
}

5. 依赖倒置原则 (Dependency Inversion Principle, DIP)

概念:高层模块不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。

例子:假设有一个 UserService 类,它直接依赖 UserDao 类。为了遵循DIP,我们应该将 UserService 类改为依赖一个 UserRepository 接口,然后 UserDao 类实现这个接口。

// 遵循DIP的设计
interface UserRepository {
    void saveUser(User user);
    User findUserById(int id);
}

class UserDao implements UserRepository {
    public void saveUser(User user) {
        // 假设的保存用户逻辑
    }

    public User findUserById(int id) {
        // 假设的根据ID查找用户逻辑
        return new User();
    }
}

class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public void registerUser(String username, String password) {
        User user = new User(username, password);
        userRepository.saveUser(user);
    }
}

6. 迪米特法则 (Law of Demeter, LoD)

概念:一个软件实体应当尽量少的与其他实体发生相互作用。这意味着我们应该尽量减少类之间的耦合,使得类更加模块化。

例子:假设有一个 OrderService 类,它需要访问 Customer 类和 ShippingAddress 类。为了遵循LoD,我们应该尽量减少 OrderService 类与其他类的交互,可以将一些数据封装在内部类或使用组合。

// 遵循LoD的设计
class OrderService {
    private CustomerService customerService;
    private ShippingAddressService shippingAddressService;

    public OrderService(CustomerService customerService, ShippingAddressService shippingAddressService) {
        this.customerService = customerService;
        this.shippingAddressService = shippingAddressService;
    }

    public void processOrder(Order order) {
        // 假设的订单处理逻辑
        Customer customer = customerService.getCustomerByName(order.getCustomerName());
        ShippingAddress shippingAddress = shippingAddressService.getShippingAddress(customer);
        // 订单处理逻辑,使用customer和shippingAddress
    }
}

class CustomerService {
    public Customer getCustomerByName(String customerName) {
        // 假设的根据名字查找客户逻辑
        return new Customer();
    }
}

class ShippingAddressService {
    public ShippingAddress getShippingAddress(Customer customer) {
        // 假设的根据客户获取配送地址逻辑
        return new ShippingAddress();
    }
}

7. 合成/聚合复用原则 (Composite/Aggregation Reuse Principle, CARP)

概念:尽量使用组合/聚合关系来达到代码复用的目的,而不是使用继承。

例子:假设有一个 Order 类,它包含一个 LineItem 列表。在这种情况下,我们不应该创建一个 LineItem 子类来表示不同的订单行项目,而应该使用组合关系,将不同的订单行项目作为 Order 类的成员对象。

// 遵循CARP的设计
class Order {
    private List<LineItem> lineItems;

    public Order() {
        this.lineItems = new ArrayList<>();
    }

    public void addLineItem(LineItem lineItem) {
        lineItems.add(lineItem);
    }
    
    public double calculateTotal() {
        double total = 0;
        for (LineItem item : lineItems) {
            total += item.getCost();
        }
        return total;
    }
}

class LineItem {
    private String name;
    private double price;

    public LineItem(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public double getCost() {
        return price;
    }
}

总结

设计模式是软件设计中的一种经验总结,它们可以用来解决常见的编程问题,提高代码的质量。然而,设计模式并不是银弹,它们也需要根据实际情况来合理使用。

正确地使用设计模式可以提高代码的可维护性和可扩展性,但错误地使用可能会增加代码复杂度、学习成本和性能开销。还是那句话,设计模式只是一个工具,不要为了使用设计模式而用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值