java之23种设计模式

发布于:2025-07-27 ⋅ 阅读:(17) ⋅ 点赞:(0)

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

  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());
}


网站公告

今日签到

点亮在社区的每一天
去签到