第三章 设计模式(2023版本IDEA)


  前面课程中已经学习了面向对象的三大特征,在后续的学习过程中对面向对象的认识会不断深入,不断提高运用面向对象思想解决问题的能力。(如果没有了解可以去我主页看看Java开发之框架基础技术第1-2章(2023版本IEDA)来学习)本章学习面向对象的一些高级应用一一设计模式。设计模式被广泛运用在java框架技术中,学习设计模式对于理解框架的工作原理会有所帮助。

学习方法
  设计模式虽有很多种,但总是可以从解锅台、提高复用性这些方向来理解。首先要明确每种设计模式的使用场景,明确其要解决的问题,进而理解其解决该问题的思路。

3.1 设计模式概述

  设计模式(Design Pattern)是人们在长期的软件开发中对一些经验的总结,是对某些特定问题经过实践检验的特定解决方法。就像兵法中的三十六计,总结了36种对于战争中某些场合的可行性计谋战术一一"围魏救赵"“声东击西”"走为上"等,可以说三十六计中的每一计都是一种模式。

  1. 创建型模式(Creational Patterns)
    创建型模式主要用于对象的创建,它们通过隐藏对象的创建逻辑来提供更大的灵活性。

示例:单例模式(Singleton Pattern)
单例模式确保一个类仅有一个实例,并提供一个全局访问点。

public class Singleton {
     
    // 私有静态变量,保存类的唯一实例  
    private static Singleton instance;  
  
    // 私有构造函数,防止外部通过new创建实例  
    private Singleton() {
   }  
  
    // 提供一个全局的静态方法,返回唯一实例  
    public static Singleton getInstance() {
     
        if (instance == null) {
     
            instance = new Singleton();  
        }  
        return instance;  
    }  
  
    // 其他方法...  
}
  1. 结构型模式(Structural Patterns)
    结构型模式关注于类、接口和对象之间的组合关系,以创建更大的结构。

示例:适配器模式(Adapter Pattern)
适配器模式将一个类的接口转换成客户端期望的另一个接口形式,使类之间的接口不兼容问题可以通过一个中间类来解决。

// 目标接口  
public interface Target {
     
    void request();  
}  
  
// 需要适配的类  
public class Adaptee {
     
    public void specificRequest() {
     
        // 具体请求  
    }  
}  
  
// 适配器类  
public class Adapter implements Target {
     
    private Adaptee adaptee;  
  
    public Adapter(Adaptee adaptee) {
     
        this.adaptee = adaptee;  
    }  
  
    @Override  
    public void request() {
     
        adaptee.specificRequest();  
    }  
}
  1. 行为型模式(Behavioral Patterns)
    行为型模式主要关注对象之间的通信和交互方式。

示例:观察者模式(Observer Pattern)
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

// 抽象主题类  
public abstract class Subject {
     
    // 维护一个观察者列表  
    private List<Observer> observers = new ArrayList<>();  
  
    // 注册观察者  
    public void registerObserver(Observer o) {
     
        observers.add(o);  
    }  
  
    // 移除观察者  
    public void removeObserver(Observer o) {
     
        observers.remove(o);  
    }  
  
    // 通知所有观察者  
    protected void notifyObservers() {
     
        for (Observer observer : observers) {
     
            observer.update(this);  
        }  
    }  
  
    // 抽象的通知方法  
    public abstract void stateChanged();  
}  
  
// 抽象观察者类  
public interface Observer {
     
    void update(Subject subject);  
}  
  
// 具体实现  
// ...(具体主题类和观察者类的实现)

注意
  上述代码示例仅用于说明设计模式的基本思想和结构,并未包含完整的错误处理和优化逻辑。在实际应用中,您可能需要根据具体需求进行调整和完善。

设计模式的学习和应用需要结合具体的项目实践,通过不断尝试和反思来加深对设计模式的理解和应用能力。

3.2 软件可复用问题和面向对象设计原则

  软件可复用问题和面向对象设计原则是两个紧密相连的概念。在软件开发中,可复用性是一个重要的目标,它旨在通过重用已有的软件组件来降低开发成本、提高开发效率和软件质量。面向对象设计原则则为实现软件的可复用性提供了指导和支持。

一、软件可复用问题

  软件复用(Software Reuse)是使用已有的软件组件去实现或更新软件系统的过程。复用可以降低开发成本、缩短开发周期、提高软件质量,并促进软件标准化。然而,要实现软件的有效复用,需要解决以下几个关键问题:

  1. 组件的明确定义和标准化:可复用的组件需要具有明确的定义和标准化的接口,以便在不同的系统中被重用。
  2. 组件的独立性:组件之间应该尽可能少地相互依赖,以提高其独立性和可移植性。
  3. 组件的文档化和可理解性:良好的文档和易于理解的设计是复用组件的前提。
  4. 组件的测试和验证:复用前需要对组件进行充分的测试和验证,以确保其稳定性和可靠性。

二、面向对象设计原则

面向对象设计原则为软件的可复用性提供了指导和支持。以下是一些关键的面向对象设计原则:

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

一个类应该仅有一个引起它变化的原因。这有助于保持类的简洁和可维护性,从而提高其可复用性。

// 示例:一个类只负责一个功能  
public class UserService {
     
    // 负责用户注册的逻辑  
    public void registerUser(User user) {
     
        // 注册逻辑...  
    }  
  
    // 如果有其他与用户相关的功能,应该放在其他类中  
}
2. 开放-封闭原则(Open-Closed Principle, OCP)

软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在添加新功能时,应该通过扩展现有系统来实现,而不是修改现有代码。这有助于保持系统的稳定性和可复用性。

// 示例:通过策略模式实现OCP  
interface PaymentStrategy {
     
    void pay(double amount);  
}  
  
class CreditCardPayment implements PaymentStrategy {
     
    public void pay(double amount) {
     
        // 信用卡支付逻辑...  
    }  
}  
  
class CashPayment implements PaymentStrategy {
     
    public void pay(double amount) {
     
        // 现金支付逻辑...  
    }  
}  
  
class PaymentProcessor {
     
    private PaymentStrategy strategy;  
  
    public PaymentProcessor(PaymentStrategy strategy) {
     
        this.strategy = strategy;  
    }  
  
    public void processPayment(double amount) {
     
        strategy.pay(amount);  
    }  
}  
  
// 客户端代码  
PaymentProcessor processor = new PaymentProcessor(new CreditCardPayment());  
processor.processPayment(100.0);

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

子类型必须能够替换掉它们的基类型。这要求子类在继承基类时,必须保持与基类相同的行为特性,以确保在父类出现的地方可以使用子类来替换。

// 父类  
class Rectangle {
     
    protected double width;  
    protected double height;  
  
    public Rectangle(double width, double height) {
     
        this.width = width;  
        this.height = height;  
    }  
  
    // 计算面积  
    public double area() {
     
        return width * height;  
    }  
}  
  
// 子类,尝试遵循里氏替换原则  
class Square extends Rectangle {
     
    // 由于Square的特殊性,这里不能直接使用父类的构造器  
    // 因为Square的宽和高必须相等  
    public Square(double side) {
     
        super(side, side); // 调用父类构造器,强制宽和高相等  
    }  
  
    // 尝试修改面积方法(但这样做可能违反里氏替换原则)  
    // @Override  
    // public double area() {  
    //     return width * width; // 直接使用width的平方,但这会破坏里氏替换原则  
    // }  
  
    // 为了保持里氏替换原则,我们不覆盖area方法  
    // 而是添加一个新的方法来计算正方形的特定属性(比如周长)  
    public double perimeter(<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值