Java设计模式的原则有哪些

发布时间:2023-01-06 17:36:14 作者:iii
来源:亿速云 阅读:300

Java设计模式的原则有哪些

目录

  1. 引言
  2. 设计模式的基本原则
  3. 设计模式的分类
  4. 常见设计模式详解
  5. 设计模式的应用场景
  6. 设计模式的优缺点
  7. 总结

引言

设计模式是软件开发中经过验证的解决方案,用于解决常见的设计问题。它们提供了一种标准化的方式来组织和设计代码,使得代码更易于理解、维护和扩展。Java作为一种广泛使用的编程语言,设计模式在其开发中扮演着重要的角色。本文将详细介绍Java设计模式的原则、分类、常见模式及其应用场景。

设计模式的基本原则

设计模式的基本原则是指导设计模式创建和应用的核心思想。这些原则帮助开发者编写出高质量、可维护和可扩展的代码。

单一职责原则

单一职责原则(Single Responsibility Principle, SRP)指出,一个类应该只有一个引起它变化的原因。换句话说,一个类应该只负责一项职责。这有助于降低类的复杂性,提高代码的可读性和可维护性。

示例:

class User {
    private String name;
    private String email;

    // 构造函数、getter和setter方法

    public void saveUser() {
        // 保存用户信息到数据库
    }

    public void sendEmail() {
        // 发送电子邮件
    }
}

在上面的示例中,User类负责保存用户信息和发送电子邮件,这违反了单一职责原则。更好的做法是将这两个职责分离到不同的类中:

class User {
    private String name;
    private String email;

    // 构造函数、getter和setter方法
}

class UserRepository {
    public void saveUser(User user) {
        // 保存用户信息到数据库
    }
}

class EmailService {
    public void sendEmail(User user) {
        // 发送电子邮件
    }
}

开闭原则

开闭原则(Open/Closed Principle, OCP)指出,软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着应该通过添加新代码来扩展系统的功能,而不是修改现有的代码。

示例:

class Rectangle {
    private double width;
    private double height;

    // 构造函数、getter和setter方法

    public double area() {
        return width * height;
    }
}

class Circle {
    private double radius;

    // 构造函数、getter和setter方法

    public double area() {
        return Math.PI * radius * radius;
    }
}

class AreaCalculator {
    public double calculateArea(Object shape) {
        if (shape instanceof Rectangle) {
            return ((Rectangle) shape).area();
        } else if (shape instanceof Circle) {
            return ((Circle) shape).area();
        }
        throw new IllegalArgumentException("Unknown shape");
    }
}

在上面的示例中,AreaCalculator类的calculateArea方法需要根据不同的形状类型进行判断,这违反了开闭原则。更好的做法是使用多态:

interface Shape {
    double area();
}

class Rectangle implements Shape {
    private double width;
    private double height;

    // 构造函数、getter和setter方法

    @Override
    public double area() {
        return width * height;
    }
}

class Circle implements Shape {
    private double radius;

    // 构造函数、getter和setter方法

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

class AreaCalculator {
    public double calculateArea(Shape shape) {
        return shape.area();
    }
}

里氏替换原则

里氏替换原则(Liskov Substitution Principle, LSP)指出,子类应该能够替换其父类并且不会影响程序的正确性。这意味着子类应该遵循父类的行为规范,不能改变父类的行为。

示例:

class Bird {
    public void fly() {
        System.out.println("Flying");
    }
}

class Ostrich extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Ostriches can't fly");
    }
}

在上面的示例中,Ostrich类继承了Bird类,但它不能飞行,这违反了里氏替换原则。更好的做法是将fly方法从Bird类中分离出来:

class Bird {
    // 其他方法
}

class FlyingBird extends Bird {
    public void fly() {
        System.out.println("Flying");
    }
}

class Ostrich extends Bird {
    // 其他方法
}

接口隔离原则

接口隔离原则(Interface Segregation Principle, ISP)指出,客户端不应该依赖于它们不需要的接口。这意味着应该将大的接口拆分成更小、更具体的接口,以便客户端只需实现它们所需的方法。

示例:

interface Worker {
    void work();
    void eat();
}

class HumanWorker implements Worker {
    @Override
    public void work() {
        System.out.println("Working");
    }

    @Override
    public void eat() {
        System.out.println("Eating");
    }
}

class RobotWorker implements Worker {
    @Override
    public void work() {
        System.out.println("Working");
    }

    @Override
    public void eat() {
        throw new UnsupportedOperationException("Robots don't eat");
    }
}

在上面的示例中,RobotWorker类不需要实现eat方法,这违反了接口隔离原则。更好的做法是将Worker接口拆分成两个更小的接口:

interface Workable {
    void work();
}

interface Eatable {
    void eat();
}

class HumanWorker implements Workable, Eatable {
    @Override
    public void work() {
        System.out.println("Working");
    }

    @Override
    public void eat() {
        System.out.println("Eating");
    }
}

class RobotWorker implements Workable {
    @Override
    public void work() {
        System.out.println("Working");
    }
}

依赖倒置原则

依赖倒置原则(Dependency Inversion Principle, DIP)指出,高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。这意味着应该通过接口或抽象类来定义依赖关系,而不是直接依赖于具体的实现。

示例:

class LightBulb {
    public void turnOn() {
        System.out.println("LightBulb: On");
    }

    public void turnOff() {
        System.out.println("LightBulb: Off");
    }
}

class Switch {
    private LightBulb bulb;

    public Switch(LightBulb bulb) {
        this.bulb = bulb;
    }

    public void operate() {
        bulb.turnOn();
    }
}

在上面的示例中,Switch类直接依赖于LightBulb类,这违反了依赖倒置原则。更好的做法是通过接口来定义依赖关系:

interface Switchable {
    void turnOn();
    void turnOff();
}

class LightBulb implements Switchable {
    @Override
    public void turnOn() {
        System.out.println("LightBulb: On");
    }

    @Override
    public void turnOff() {
        System.out.println("LightBulb: Off");
    }
}

class Switch {
    private Switchable device;

    public Switch(Switchable device) {
        this.device = device;
    }

    public void operate() {
        device.turnOn();
    }
}

设计模式的分类

设计模式通常分为三大类:创建型模式、结构型模式和行为型模式。每一类模式都有其特定的用途和应用场景。

创建型模式

创建型模式关注对象的创建过程,旨在将对象的创建与使用分离,使得系统更加灵活和可扩展。常见的创建型模式包括:

结构型模式

结构型模式关注类和对象的组合,旨在通过组合来形成更大的结构,使得系统更加灵活和可扩展。常见的结构型模式包括:

行为型模式

行为型模式关注对象之间的交互和职责分配,旨在使对象之间的交互更加灵活和可扩展。常见的行为型模式包括:

常见设计模式详解

单例模式

单例模式确保一个类只有一个实例,并提供一个全局访问点。它通常用于控制资源的访问,例如数据库连接或线程池。

示例:

class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

工厂模式

工厂模式定义了一个创建对象的接口,但由子类决定实例化哪个类。它将对象的创建与使用分离,使得系统更加灵活。

示例:

interface Product {
    void use();
}

class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

class Factory {
    public Product createProduct(String type) {
        if (type.equals("A")) {
            return new ConcreteProductA();
        } else if (type.equals("B")) {
            return new ConcreteProductB();
        }
        throw new IllegalArgumentException("Unknown product type");
    }
}

抽象工厂模式

抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。它通常用于创建一组相关的对象。

示例:

interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}

class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

建造者模式

建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。它通常用于创建复杂的对象。

示例:

class Product {
    private String partA;
    private String partB;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    @Override
    public String toString() {
        return "Product [partA=" + partA + ", partB=" + partB + "]";
    }
}

class Builder {
    private Product product = new Product();

    public void buildPartA(String partA) {
        product.setPartA(partA);
    }

    public void buildPartB(String partB) {
        product.setPartB(partB);
    }

    public Product getResult() {
        return product;
    }
}

原型模式

原型模式通过复制现有对象来创建新对象,而不是通过实例化类。它通常用于创建成本较高的对象。

示例:

class Prototype implements Cloneable {
    private String field;

    public Prototype(String field) {
        this.field = field;
    }

    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String toString() {
        return "Prototype [field=" + field + "]";
    }
}

适配器模式

适配器模式将一个类的接口转换成客户端期望的另一个接口,使得原本不兼容的类可以一起工作。它通常用于集成现有的类或库。

示例:

interface Target {
    void request();
}

class Adaptee {
    public void specificRequest() {
        System.out.println("Specific request");
    }
}

class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

桥接模式

桥接模式将抽象部分与实现部分分离,使它们可以独立变化。它通常用于处理多维度变化的问题。

示例:

interface Implementor {
    void operationImpl();
}

class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorA operation");
    }
}

class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorB operation");
    }
}

abstract class Abstraction {
    protected Implementor implementor;

    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    public abstract void operation();
}

class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operation() {
        implementor.operationImpl();
    }
}

组合模式

组合模式将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端可以统一处理单个对象和组合对象。它通常用于处理树形结构的数据。

示例:

interface Component {
    void operation();
}

class Leaf implements Component {
    @Override
    public void operation() {
        System.out.println("Leaf operation");
    }
}

class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public void operation() {
        for (Component component : children) {
            component.operation();
        }
    }
}

装饰器模式

装饰器模式动态地给对象添加额外的职责,而不改变其结构。它通常用于扩展对象的功能。

示例:

interface Component {
    void operation();
}

class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}

class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}

class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("ConcreteDecoratorA operation");
    }
}

class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("ConcreteDecoratorB operation");
    }
}

外观模式

外观模式为子系统中的一组接口提供了一个统一的接口,使得子系统更易于使用。它通常用于简化复杂系统的接口。

示例:

class SubsystemA {
    public void operationA() {
        System.out.println("SubsystemA operation");
    }
}

class SubsystemB {
    public void operationB() {
        System.out.println("SubsystemB operation");
    }
}

class Facade {
    private SubsystemA subsystemA = new SubsystemA();
    private SubsystemB subsystemB = new SubsystemB();

    public void operation() {
        subsystemA.operationA();
        subsystemB.operationB();
    }
}

享元模式

享元模式通过共享技术有效地支持大量细粒度的对象。它通常用于减少内存使用和提高性能。

示例:

class Flyweight {
    private String intrinsicState;

    public Flyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    public void operation(String extrinsicState) {
        System.out.println("Intrinsic State: " + intrinsicState);
        System.out.println("Extrinsic State: " + extrinsicState);
    }
}

class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String key) {
        if (!flyweights.containsKey(key)) {
            flyweights.put(key, new Flyweight(key));
        }
        return flyweights.get(key);
    }
}

代理模式

代理模式为其他对象提供一个代理以控制对这个对象的访问。它通常用于延迟加载、访问控制、日志记录等。

示例:

”`java interface Subject { void request(); }

class RealSubject implements Subject { @Override

推荐阅读:
  1. java设计模式中有哪些原则
  2. 详解Java设计模式常用原则

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:C语言指针数组和数组指针的区别有哪些

下一篇:Java数据结构之常见排序算法怎么实现

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》