当前位置: 首页 > news >正文

java之23种设计模式

编写软件过程中程序员面临着来自耦合性、内聚性、可维护性、重用性、灵活性等多方面的挑战,设计模式遵循以下原则:

  1. 单一原则:一个类负责一个职责。
  2. 接口隔离原则:一个类对另一个类的依赖应该建立在最小接口上。一个类不必要实现接口中的所有方法,此时可以根据方法将接口拆分成多个接口。
  3. 依赖倒转原则【Dependence Inversion Principle】:高层模块不应该依赖底层模块,二者均应该依赖其抽象、抽象不应该依赖细节,细节应该依赖抽象、依赖倒转的中心思想是面向接口编程。、依赖倒转原则是基于这样的设计理念:相较于细节的多边形,抽象的东西要稳定的多。以抽象为基础搭建的架构比细节为基础的架构要稳定的多。Java中抽象是指接口或者抽象类,细节就是具体的实习类。使用接口或者抽象类的目的是指定好规范,而不涉及任何具体的操作,把展现细节的任务交给实现类完
  4. 里氏替换原则。
  5. 开闭原则。
  6. 迪米特法则。
  7. 合成复用原则:尽量使用合成或者聚合的方式,而不是继承方式。

1.设计模式的分类


1. 创建型模式(Creational):关注对象的实例化过程,包括了如何实例化对象、隐藏对象的创建细节等。常见的创建型模式有单例模式、工厂模式、抽象工厂模式等。
2. 结构型模式(Structural):关注对象之间的组合方式,以达到构建更大结构的目标。这些模式帮助你定义对象之间的关系,从而实现更大的结构。常见的结构型模式有适配器模式、装饰器模式、代理模式等。
3. 行为型模式(Behavioral):关注对象之间的通信方式,以及如何合作共同完成任务。这些模式涉及到对象之间的交互、责任分配等。常见的行为型模式有观察者模式、策略模式、命令模式等。


2.设计模式概览

装饰着模式核心目的是增强目标类的功能。
适配器模式是为了适配多个目标类|接口之间的功能。
模版模式核心目的是子类共享抽象父类的公共逻辑。
策略模式核心目的是灵活地选择和切换不同的算法,同时又不影响到客户端代码。

23种设计模式的实现方式


3.设计模式间的关系


4.设计模式详情


4.1.适配器模式【Adapter or Wrapper】

适配器模式属于结构型模式,主要分为三类:类适配器模式、对象适配器模式、接口适配器模式。

问题:当你有两个不兼容的接口(即类或对象),但需要它们能够一起工作时,适配器模式可以解决这个问题。例如,你可能有一个已存在的类库或组件,但其接口与你的代码不匹配,你希望能够无缝地将它们集成在一起。

解决方案:适配器模式通过引入一个适配器类来充当中间人,将一个接口转换成另一个接口,使得两个不兼容的对象能够协同工作。适配器类包含一个对不兼容接口的引用,并实现了你期望的目标接口。这样,当你需要使用目标接口的时候,可以通过适配器来调用原本不兼容的类的方法。

效果:适配器模式的应用可以使得现有的代码与新代码能够无缝协同工作,从而提高了代码的可重用性。它允许你将不同系统、库或组件整合在一起,而无需对现有代码进行大量修改。然而,适配器模式也可能引入一些复杂性,因为你需要维护适配器类和处理不同接口之间的映射关系。

总的来说,适配器模式是一种很有用的模式,特别适合在集成不同组件或类时,解决接口不匹配的问题,从而保持代码的灵活性和可维护性。

public class LegacyRectangle {
    public void display(int x1, int y1, int x2, int y2) {
        System.out.println("LegacyRectangle: Point1(" + x1 + ", " + y1 + "), Point2(" + x2 + ", " + y2 + ")");
    }
}
public interface Shape {
    void draw(int x, int y, int width, int height);
}
/**
 * 将LegacyRectangle适配到Shape接口上
 */
public class RectangleAdapter implements Shape{
    private LegacyRectangle legacyRectangle;
    public RectangleAdapter(LegacyRectangle legacyRectangle){
        this.legacyRectangle = legacyRectangle;
    }
    @Override
    public void draw(int x, int y, int width, int height) {
        int x1 = x;
        int y1 = y;
        int x2 = x + width;
        int y2 = y + height;
        legacyRectangle.display(x1, y1, x2, y2);
    }
}
public class Test {
    public static void main(String[] args) {
        LegacyRectangle legacyRectangle = new LegacyRectangle();
        Shape shapeAdapter = new RectangleAdapter(legacyRectangle);
        shapeAdapter.draw(10, 20, 50, 30);
    }
}

4.2.装饰着模式(Decorator)

问题:在某些情况下,我们需要在不修改现有对象结构的情况下,动态地添加功能或责任。继承在这种情况下可能会导致类爆炸问题,而且修改现有类可能会影响到其他部分的代码。

解决方案:装饰模式提供了一种在运行时动态地为对象添加新功能的方法,通过创建一个装饰类来包装原始类。装饰类具有与原始类相同的接口,它内部包含一个指向原始对象的引用,并且可以根据需要包装额外的功能。这样,你可以通过组合不同的装饰类来构建出具有不同功能组合的对象。

效果:装饰模式的优点包括避免了类爆炸问题,因为你可以通过组合少量的装饰类来实现各种功能组合。它也使得功能的增加和修改更加灵活,不会影响到其他部分的代码。然而,装饰模式可能会导致增加很多小型的类,从而增加了代码的复杂性。

在装饰模式中,通常涉及以下角色:

  • 组件(Component):定义了一个抽象的接口,可以是具体对象或装饰器所共有的接口。
  • 具体组件(Concrete Component):实现了组件接口,是被装饰的原始对象。
  • 装饰器(Decorator):持有一个指向组件对象的引用,并实现了组件的接口。它可以包含额外的功能,也可以将请求传递给组件对象。
  • 具体装饰器(Concrete Decorator):扩展了装饰器类,通过添加额外的功能来装饰具体组件。

通过这种方式,装饰模式允许你将功能嵌套地堆叠在一起,以实现各种不同的功能组合,同时保持代码的灵活性和可维护性。

public interface Coffee {//组件
    double cost();
    String description();
}
public class SimpleCoffee implements Coffee{//具体组件
    @Override
    public double cost() {
        return 0;
    }
    @Override
    public String description() {
        return "咖啡基本功能...";
    }
}
public abstract class CoffeeDecorator implements Coffee{//抽象装饰类
    protected Coffee decoratedCoffee;
    public CoffeeDecorator(Coffee decoratedCoffee){
        this.decoratedCoffee = decoratedCoffee;
    }
    @Override
    public double cost() {
        return decoratedCoffee.cost();
    }
    @Override
    public String description() {
        return decoratedCoffee.description();
    }
}
public class MilkDecorator extends CoffeeDecorator{
    public MilkDecorator(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }
    @Override
    public double cost() {
        return super.cost() + 1.0;
    }
    @Override
    public String description() {
        return super.description() + ",with milk";
    }
}
public class SugarDecorator extends CoffeeDecorator{
    public SugarDecorator(Coffee decoratedCoffee) {
        super(decoratedCoffee);
    }    @Override
    public double cost() {
        return super.cost() + 2.0;
    }    @Override
    public String description() {
        return super.description() + ",with sugar";
    }
}
public static void main(String[] args) {
    Coffee simpleCoffee = new SimpleCoffee();
    Coffee milk = new MilkDecorator(simpleCoffee);//咖啡加牛奶
    Coffee sugar = new SugarDecorator(milk);//咖啡加牛奶加糖
    System.out.println("price = " + sugar.cost() + ", desc = " + sugar.description());
}

4.3.模版方法模式【Template Method】

问题:当你在设计一个类或一组类时,发现有一些算法的结构是固定的,但其中的某些步骤可能会因应用情境或子类的不同而变化。你希望将这个

http://www.dtcms.com/a/299471.html

相关文章:

  • 设计模式:Memento 模式详解
  • 简单实现支付密码的页面及输入效果
  • 面条式代码(Spaghetti Code)
  • Java高级之基于Java Attach与Byte-Buddy实现SQL语句增强
  • JWT安全机制与最佳实践详解
  • Linux 系统调用详解:操作文件的常用系统调用
  • Vulnhub jangow-01-1.0.1靶机渗透攻略详解
  • 自定义定时任务功能详解
  • MySQL 表的约束
  • 【面板数据】中国A股上市公司制造业智能制造数据集(1992-2024年)
  • 基于图神经网络的星间路由与计算卸载强化学习算法设计与实现
  • java实现一个方法,isTure则程序继续往下,为false则return的链式写法
  • 零基础学习性能测试第三章:jmeter线程组组合
  • LeetCode|Day26|191. 位 1 的个数|Python刷题笔记
  • Java学习|黑马笔记|Day23】网络编程、反射、动态代理
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年7月26日第150弹
  • 在Power Automate Desktop中执行PowerShell获取SharePoint online某个文件夹的用户权限列表
  • SAP ABAP的数据通过调用泛微Restful API同步数据到OA建模表
  • 学习日志19 python
  • pytest中的rerunfailures的插件(失败重试)
  • 在 Scintilla 中为 Squirrel 语言设置语法解析器的方法
  • 【Kubernetes】使用StatefulSet进行的资源调度,扩缩容,更改配置到版本回滚,三种配置更新方式
  • c#中让图片显示清晰
  • 三、平衡桥电路
  • 060_泛型擦除与边界限定
  • MySQL数据库SQL语句进阶篇——连接查询与子查询详解
  • Traffic Lights set的使用
  • CSS变量与Houdini自定义属性:解锁样式编程新维度
  • Go 语言函数设计原则:避免修改传入参数
  • MCU中的GPIO(通用输入/输出)是什么?