【23种设计模式应用场景汇总】

news2024/11/19 9:21:43

23种设计模式应用场景汇总


23种设计模式

设计模式是一种在软件开发中解决特定问题的通用解决方案。下面我将尝试将23种设计模式融入到一个场景中:
假设我们正在开发一个在线购物系统,我们可以使用以下设计模式:

  • 1. 工厂方法模式:当用户在网站上下订单时,我们可以使用工厂方法模式来创建订单对象,根据用户选择的商品类型,使用不同的工厂来创建相应的订单对象。

分为:工厂模式分为:简单工厂、工厂方法、抽象工厂。
1、简单工厂通过参数决定创建哪个实例、
2、工厂方法将工厂、产品提出抽象接口、每一种产品对应一个工厂,最后根据用户的参数,使用不同的工厂创建不同的产品实例。
3、抽象工厂:是一个工厂创建一系列产品(比如windos上的GUI组件:windows版本的按钮、文本框、选择按钮等,是与linux或MacOs下的不同)。产品1(A系列产品1、B系列产品2),产品2(A系统产品2、B系列产品2),工厂(A系列工厂、B系列工厂),A工厂就会创建A系列产品1、A系列产品2;B工厂创建B系列产品1、B系列产品2.

  • 2. 单例模式:我们可以使用单例模式来确保系统中的购物车对象只有一个实例,以确保用户在整个会话期间都使用同一个购物车。

懒汉式和饿汉式。五种,最重要的是线程安全。

  • 3. 观察者模式:当用户下订单时,我们可以使用观察者模式通知库存管理系统和仓库系统更新库存。这样,一旦有商品被下单,其他系统就会及时得到通知。

观察者模式

  1. java中提供了类Observable,只需要继承此类即可将子类变成Subject(被观察者)
  2. 被观察者持有观察者的引用,所以subject的状态发生变化后,就可以通知到观察者
  3. 观察者需要实现Observer, 重写update方法。
  • 4. 策略模式:在计算订单总价时,我们可以根据用户的会员等级或者促销活动来选择不同的计价策略,这就是策略模式的应用。
  1. 具体的角色有: strategy(一个抽象类或接口)
  2. 具体策略ConcreteStrategy(提供不同的算法)
  3. 环境角色:context 持有策略的引用,负责根据在运行时的需求选择并设置具体的策略对象。与客户端进行交互,通过使用策略对象执行相应的操作或计算。
  • 5. 适配器模式:当我们需要将外部支付f接口整合到系统中时,我们可能需要使用适配器模式来将外部接口适配成我们系统内部的统一接口。

三个角色:Target目标类、源Adaptee、适配器Adapter

  1. 目标角色定义了客户端所期待的接口,也就是客户程序需要调用的方法。它是适配器要转换到的目标接口
  2. 源角色是现有的接口或实现类,它拥有需要被适配的功能,但其接口与目标不兼容。
  3. 适配器角色实现了目标接口,并持有对源对象的引用,负责将源对象的接口转换为与目标接口兼容的形式。
    适配器模式的关键在于,通过创建一个适配器类来解决现有类与期望接口之间的不匹配问题,使得原本由于接口不兼容而无法协同工作的两个系统可以协同工作。

分类: 在具体实现中,适配器模式可以分为两种类型

  • 类适配器:适配器类继承自源角色,并实现目标接口,所以适配器既可以调用源角色的方法,又能提供目标接口要求的方法。
  • 对象适配器:适配器类实现目标接口,并持有一个源对象实例作为成员变量,通过调用源对象的方法来完成目标接口的实现
  • 6. 装饰者模式:如果我们需要在订单中加入礼品包装、贺卡等功能,可以使用装饰者模式动态地为订单对象添加额外的功能。

装饰者功能

  1. 扩展功能:当需要向现有的类中添加新的行为或职责时,尤其是不能直接修改原始类的源代码的情况下,可以使用装饰者模式动态地将新功能附加到对象上。
  2. 灵活组合出各种特性的对象:通过不同的装饰者排列组合,可以构建出不同特性的对象,实现多种功能的可插拔式组合。
  3. 装饰者对象与被装饰的对象具有相同的超类型,客户端程序无需知道是否进行了装饰以及如何装饰的细节,只需面向统一的接口进行操作即可。

角色

  1. component:定义了一个对象接口,可以给这些对象动态添加职责。
  2. ConcreteComponent:具体的原始组件对象,实现了Component接口。
  3. Decorator: 抽象装饰者类,继承自Component,从外类扩展Component类的功能,维持了与Component相同的接口。
  4. ConcreteDecorator:具体装饰类,实现了Decorator接口,并维持对Component对象的引用,在其方法中既可以调用原始对象的方法,也可以增加额外的操作。
  • 7. 命令模式:在处理用户的退货请求时,我们可以使用命令模式将用户的退货请求封装成命令对象,然后由相应的命令对象来执行具体的退货操作。

角色分类:

  1. 调用者/请求者(Invoker)
  2. 抽象命令(Command)和具体命令(concreteCommand)
  3. 接收者(Receiver)
  4. 客户端Client


调用链:       客户端 ——> 调用者 ——> 命令——> 接受者

  • 8. 模板方法模式:在生成订单报告时,我们可以使用模板方法模式定义生成报告的流程,然后在具体的报告生成类中实现具体的步骤。

角色

  1. 抽象类(Abstract Class/Template Class)
    * 定义了一个或多个抽象操作方法,用于子类去实现。同时定义了一个或多个具体方法(通常包括一个或多个框架方法),这些方法可以是一个完整的算法骨架,包含了整个算法的固定步骤。
  2. 具体子类(concrete subClass)
    实现了抽象类中所声 明的抽象操作。每个子类提供了一种不同的算法实现方式。
    子类在实现抽象方法时填充模版方法预留的"空洞",从而完成特定的业务逻辑。

功能

  • 模版方法模式通过将不变的行为(即模版方法)放在抽象类中,并将可变的行为(即抽象方法)留给子类去实现,实现了代码复用和对算法结构的控制。子类可以在不改变算法整体结构的前提下,重新定义部分步骤,以适应不同的应用场景。
  • 9. 原型模式:在系统中有一些商品是定制化的,我们可以使用原型模式来克隆商品对象,以便快速创建定制化商品的副本。

角色分类:

  1. 抽象原型类(prototype Interface/Abstract Prototype class)
    定义了一个克隆自身的接口,通常包含一个clone()方法,它是所有具体原型类必须实现的方法。
  2. 具体原型类(Concrete Prototype Class)
    实现了抽象原型类所声明的clone()方法,该方法可以创建并返回一个新的对象实例,这个新实例是当前对象的一个深拷贝或者浅拷贝。
    具体原型类包含了定义对象状态的所有必要属性和行为。
  3. 客户端(Client)
    创建并使用具体原型类的对象,通过调用原型对象的clone()方法来复制出新的对象实例,而不是直接通过new关键字创建新对象。
  • 10. 抽象工厂模式:如果我们的系统需要支持多个不同类型的支付方式(比如信用卡、支付宝、微信支付等),我们可以使用抽象工厂模式来创建不同支付方式的工厂,从而实现一个统一的支付接口。
  • 11. 建造者模式:当用户在网站上定制礼篮时,我们可以使用建造者模式来创建复杂的礼篮对象,将其构建过程与表示分离,使得构建过程可以创建不同的表示。

角色:

  1. 抽象建造者:
    – 定义了一个创建产品的接口,声明了一系列用于构建产品对象的方法。这些方法通常按特定的顺序调用以逐步构造整个产品对象。
  2. 具体建造者:
    – 实现了抽象建造者接口,并提供构造和装配产品的各个部件的具体实现。在建造过程完成后,它还提供了获取最终产品的接口或方法。
  3. 产品:
    – 是建造者模式所要创建的对象类型。可以是一个复杂的对象,包含多个属性或者子组件。
  4. 导演者/指挥者(Director):
    – 负责控制建造过程,协调各个步骤的执行顺序。它可以独立于具体建造者角色而变化,不依赖于具体的构建细节。
    指挥者 ——> 建造者 ——> 产品
/**
 示例代码
 作者: LeKu_yuan
*/
// 1. 抽象建造者
public abstract class AbstractComputerBuilder {
    protected Computer computer = new Computer();

    public abstract void buildCPU();
    public abstract void buildMemory();
    public abstract void buildHardDrive();

    // 返回最终产品
    public Computer getComputer() {
        return computer;
    }
}

// 2. 具体建造者
public class HighPerformanceComputerBuilder extends AbstractComputerBuilder {
    @Override
    public void buildCPU() {
        computer.setCpu("Intel Core i9");
    }

    @Override
    public void buildMemory() {
        computer.setMemory("64GB DDR5 RAM");
    }

    @Override
    public void buildHardDrive() {
        computer.setHardDrive("2TB SSD");
    }
}

// 3. 产品
public class Computer {
    private String cpu;
    private String memory;
    private String hardDrive;

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String getHardDrive() {
        return hardDrive;
    }

    public void setHardDrive(String hardDrive) {
        this.hardDrive = hardDrive;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", hardDrive='" + hardDrive + '\'' +
                '}';
    }
}

// (4. 可选角色)导演者/指挥者
public class Director {
    private AbstractComputerBuilder builder;

    public Director(AbstractComputerBuilder builder) {
        this.builder = builder;
    }

    public Computer constructComputer() {
        builder.buildCPU();
        builder.buildMemory();
        builder.buildHardDrive();
        return builder.getComputer();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Director director = new Director(new HighPerformanceComputerBuilder());
        Computer highPerformanceComputer = director.constructComputer();
        System.out.println(highPerformanceComputer);
    }
}

  • 12. 状态模式:在订单处理流程中,订单可能会经历多个状态(比如待支付、已支付、已发货、已签收等),我们可以使用状态模式来管理订单的状态转换,使状态转换更加清晰和可维护。

角色:

  1. 抽象状态类:定义所有具体状态角色需要实现的接口或抽象类
  2. 具体状态类:实现抽象状态角色所定义的接口,即为系统可能处于的各种状态提供具体的实现。
  3. 上下文:也称为上下文,是使用状态模式的类,它维护一个指向当前状态对象的引用

abstract class TrafficLightState {
   protected TrafficLight trafficLight;
   public void setTrafficLight(TrafficLight trafficLight) {
       this.trafficLight = trafficLight;
   }
   
   // 抽象方法,由具体状态实现
   public abstract void turnOn();
   public abstract void turnOff();
   public abstract void changeToNextState();
   
}

 // 具体状态角色(Concrete State)
class RedLightState extends TrafficLightState {
    @Override
    public void turnOn() {
        System.out.println("红灯亮起");
    }

    @Override
    public void turnOff() {
        System.out.println("红灯熄灭");
    }
    
    @Override
    public void changeToNextState() {
        trafficLight.setState(trafficLight.getYellowLightState());
    }
}

class YellowLightState extends TrafficLightState {
   @Override
   public void turnOn() {
       System.out.println("黄灯亮起");
   }

   @Override
   public void turnOff() {
       System.out.println("黄灯熄灭");
   }

   @Override
   public void changeToNextState() {
       trafficLight.setState(trafficLight.getGreenLightState());
   }
}

class GreenLightState extends TrafficLightState {
   @Override
   public void turnOn() {
       System.out.println("绿灯亮起");
   }

   @Override
   public void turnOff() {
       System.out.println("绿灯熄灭");
   }

   @Override
   public void changeToNextState() {
       trafficLight.setState(trafficLight.getRedLightState());
   }
}

 // 环境角色(Context)
public class TrafficLight {
   private TrafficLightState currentState;

   public TrafficLight() {
       currentState = new RedLightState();
       currentState.setTrafficLight(this);
   }

   public TrafficLightState getRedLightState() {
       return new RedLightState();
   }

   public TrafficLightState getYellowLightState() {
       return new YellowLightState();
   }

   public TrafficLightState getGreenLightState() {
       return new GreenLightState();
   }

   public void setState(TrafficLightState state) {
       currentState = state;
       currentState.turnOn();
   }

   public void changeLights() {
       currentState.changeToNextState();
   }
}

// 使用示例
public class Main {
   public static void main(String[] args) {
       TrafficLight trafficLight = new TrafficLight();
       trafficLight.changeLights();  // 输出:红灯亮起
       trafficLight.changeLights();  // 输出:黄灯亮起
       trafficLight.changeLights();  // 输出:绿灯亮起
       trafficLight.changeLights();  // 输出:红灯亮起
   }
}
  • 13. 桥接模式:如果我们需要在不同的平台上展示商品信息(比如网站、移动端、微信小程序等),我们可以使用桥接模式平台和商品信息的展示进行解耦,从而让它们可以独立地变化

桥接模式(Bridge Pattern)是一种结构设计模式,它将抽象部分与它的实现部分分离,使它们都可以独立地变化。


角色

  1. 抽象化角色(Abstraction): 这是抽象类,定义了抽象接口,维护一个对实现化角色的引用。与客户端进行交互
  2. 扩展抽象化角色(Refined Abstraction): 这是抽象化角色的子类,可以提供额外的功能和方法,或者修改从抽象化继承的方法行为,但仍然包含对实现化角色的引用。
  3. 实现化角色(Implementor):
    这是一个接口或抽象类,定义了实现化角色需要实现的一组接口方法。
    实现化角色不依赖于抽象化角色,它定义了实现功能的具体结构和算法
  4. 具体实现化角色(Concrete Implementor)
    这是实现化角色的具体实现类,实现了接口或抽象类定义的所有方法,为抽象化角色提供了具体的实现方案。

总结: 将两个变化的因素分割开,利用笛卡尔积使其组合,而不是创建笛卡尔积个类模版。


例子: 比如形状和颜色,不同的形状需要不同的颜色,这个可以分开。

//  **代码演示**:
// 实现化角色(Implementor)
interface ColorStrategy {
    void applyColor();
}

// 具体实现化角色(Concrete Implementor)
class RedColorStrategy implements ColorStrategy {
    @Override
    public void applyColor() {
        System.out.println("应用红色填充");
    }
}

class GreenColorStrategy implements ColorStrategy {
    @Override
    public void applyColor() {
        System.out.println("应用绿色填充");
    }
}

// 抽象化角色(Abstraction)
abstract class Shape {
    protected ColorStrategy color;

    public Shape(ColorStrategy color) {
        this.color = color;
    }

    public abstract void draw();

    public void setColor(ColorStrategy color) {
        this.color = color;
    }
}

// 扩展抽象化角色(Refined Abstraction)
class Circle extends Shape {
    public Circle(ColorStrategy color) {
        super(color);
    }

    @Override
    public void draw() {
        System.out.println("绘制圆形...");
        color.applyColor(); // 应用颜色填充策略
    }
}

class Square extends Shape {
    public Square(ColorStrategy color) {
        super(color);
    }

    @Override
    public void draw() {
        System.out.println("绘制正方形...");
        color.applyColor(); // 应用颜色填充策略
    }
}

// 使用示例
public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape circle1 = new Circle(new RedColorStrategy());
        Shape square1 = new Square(new GreenColorStrategy());

        circle1.draw();  // 输出:绘制圆形... 应用红色填充
        square1.draw();   // 输出:绘制正方形... 应用绿色填充

        circle1.setColor(new GreenColorStrategy());
        square1.setColor(new RedColorStrategy());

        circle1.draw();  // 输出:绘制圆形... 应用绿色填充
        square1.draw();   // 输出:绘制正方形... 应用红色填充
    }
}

  • 14. 组合模式:在管理商品分类树的时候,我们可以使用组合模式来表示商品分类和子分类的层次结构,以便对整个分类树进行统一的操作。

角色

  1. Component(抽象构件):定义了所有组件(包括叶子组件和容器组件)共享的接口。这些方法可能包括添加、删除子组件,以及一些针对整个组件树的通用操作。
  2. Leaf(叶子构件):表示组合结构中的叶节点对象,其没有子节点。实现了 Component 接口,并提供了相应的业务逻辑。
  3. Composite(容器构件):定义了有子节点的组合对象,同样实现 Component 接口,并提供管理子组件的方法。容器构件可以包含零个或多个其他 Component 对象。

总结

  • 通过组合模式的应用,可以让用户对单个对象和复合对象的使用具有统一性和一致性,同时能够灵活地遍历整个结构并对每个元素进行相同的操作处理。
// 抽象构件(Component)
interface FileSystemObject {
    void add(FileSystemObject obj);
    void remove(FileSystemObject obj);
    void display(int depth);
}

// 叶子构件(Leaf)
class File implements FileSystemObject {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void add(FileSystemObject obj) {
        throw new UnsupportedOperationException("Files cannot contain other objects");
    }

    @Override
    public void remove(FileSystemObject obj) {
        throw new UnsupportedOperationException("Files cannot contain other objects");
    }

    @Override
    public void display(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("-");
        }
        System.out.println(name);
    }
}

// 容器构件(Composite)
class Directory implements FileSystemObject {
    private List<FileSystemObject> children;
    private String name;

    public Directory(String name) {
        this.name = name;
        this.children = new ArrayList<>();
    }

    @Override
    public void add(FileSystemObject obj) {
        children.add(obj);
    }

    @Override
    public void remove(FileSystemObject obj) {
        children.remove(obj);
    }

    @Override
    public void display(int depth) {
        for (int i = 0; i < depth; i++) {
            System.out.print("-");
        }
        System.out.println(name);

        for (FileSystemObject child : children) {
            child.display(depth + 1);
        }
    }
}

// 使用示例
public class CompositePatternDemo {
    public static void main(String[] args) {
        Directory root = new Directory("Root");
        Directory dir1 = new Directory("Dir1");
        Directory dir2 = new Directory("Dir2");
        File file1 = new File("File1.txt");
        File file2 = new File("File2.txt");

        root.add(dir1);
        root.add(dir2);
        dir1.add(file1);
        dir2.add(file2);

        root.display(0);
    }
}
  • 15. 迭代器模式:当需要遍历购物车中的商品列表时,我们可以使用迭代器模式来提供一种统一的方式来遍历不同类型的购物车。
  • 16. 访问者模式:如果需要对不同类型的商品进行不同的操作(比如打印、计算价格等),我们可以使用访问者模式来实现对商品的不同操作,而不需要修改商品类的代码。

角色

  1. Element(元素接口):声明接受访问者对象的 accept() 方法,这是所有需要被访问的对象必须实现的接口。
  2. ConcreteElement(具体元素):实现了 Element 接口的具体元素类,它们可以是多种不同的业务>对象,每个类都提供 accept() 方法,并且可能有各自不同的内部结构和状态。
  3. Visitor(访问者接口):声明了对每一个 ConcreteElement 的访问操作,通常以方法的形式存在,每一个方法对应一种具体的元素类型。
  4. ConcreteVisitor(具体访问者):实现了 Visitor 接口的具体访问者类,为每个 visit() 方法提供了具体的实现,从而定义了针对不同元素的操作逻辑。
  5. ObjectStructure(对象结构):能够存储并遍历元素集合,它可以是一个容器或者一个复合对象,提供一个方法来允许访问者访问它的元素。

总结

  • 使用访问者模式的一个典型场景是在一个对象结构中执行某种特定操作,但又不想让这些操作侵入到各个元素类中。例如,在编译器的不同阶段(语法分析、语义分析等),对AST(抽象语法树)节点进行操作时,就可以采用访问者模式。
  • 数据结构与操作分离、避免操作入侵数据
// Element 接口
interface Animal {
    void accept(AnimalOperation operation);
}

// ConcreteElement 类
class Lion implements Animal {
    @Override
    public void accept(AnimalOperation operation) {
        operation.visit(this);
    }
    
    // 其他 Lion 类相关的方法...
}

class Elephant implements Animal {
    @Override
    public void accept(AnimalOperation operation) {
        operation.visit(this);
    }
    
    // 其他 Elephant 类相关的方法...
}

// Visitor 接口
interface AnimalOperation {
    void visit(Lion lion);
    void visit(Elephant elephant);
}

// ConcreteVisitor 类
class FeedVisitor implements AnimalOperation {
    @Override
    public void visit(Lion lion) {
        System.out.println("Feeding the lion");
    }

    @Override
    public void visit(Elephant elephant) {
        System.out.println("Feeding the elephant");
    }
}

class CleanVisitor implements AnimalOperation {
    @Override
    public void visit(Lion lion) {
        System.out.println("Cleaning the lion's habitat");
    }

    @Override
    public void visit(Elephant elephant) {
        System.out.println("Cleaning the elephant's habitat");
    }
}

// ObjectStructure
class Zoo {
    private List<Animal> animals;

    public void addAnimal(Animal animal) {
        animals.add(animal);
    }

    public void performOperation(AnimalOperation operation) {
        for (Animal animal : animals) {
            animal.accept(operation);
        }
    }
}

// 使用示例
public class VisitorPatternDemo {
    public static void main(String[] args) {
        Zoo zoo = new Zoo();
        zoo.addAnimal(new Lion());
        zoo.addAnimal(new Elephant());

        AnimalOperation feedVisitor = new FeedVisitor();
        zoo.performOperation(feedVisitor); 

        AnimalOperation cleanVisitor = new CleanVisitor();
        zoo.performOperation(cleanVisitor);
    }
}

  • 17. 备忘录模式:在用户进行购物车操作时,我们可以使用备忘录模式来保存购物车的状态,以便用户可以在需要时恢复到之前的状态。

备忘操作需要:操作人、备忘的对象(内容、数据)、备忘薄


角色

  1. Originator(发起对象)
  2. Memento(备忘录)
  3. Caretaker(负责对象)

好处:
利用其他扩展恢复数据,而不是增加本身的复杂性。

  • 18. 解释器模式:如果我们需要实现一些复杂的促销规则或者查询条件,可以使用解释器模式来定义一个解释器,用于解释和执行这些规则或者条件。

角色

  1. AbstractExpression(抽象表达式):
    这是所有具体表达式的基类或者接口,声明了一个抽象的解释方法 interpret()。
    具体的解释操作由子类实现。
  2. TerminalExpression(终结符表达式):
    终结符表达式是文法中的原子元素,通常对应于文法中的基本符号或关键字。
    实现了 AbstractExpression 接口,并为特定的终结符提供了解释逻辑。
  3. NonterminalExpression(非终结符表达式):
    非终结符表达式通常是更复杂的表达式结构,它们可能包含其他表达式(包括终结符和非终结符)。
    同样实现了 AbstractExpression 接口,其解释方法可能根据包含的子表达式进行递归调用以完成复杂表达式的解释过程。
  4. Context(上下文环境):
    上下文环境角色包含了解释过程中需要的所有全局信息,比如变量、状态等,可以被各个表达式访问并影响它们的解释结果。
    有时上下文环境会作为参数传递给表达式解释方法,或者作为表达式对象的一个成员变量。
  • 19. 中介者模式:当订单系统、库存系统和物流系统之间需要进行协作时,我们可以使用中介者模式来将它们的交互行为封装到中介者对象中,从而降低系统中各个对象之间的耦合度。

预览

  • 中介者模式(Mediator Pattern)是一种行为设计模式,它通过引入一个中介对象来封装一系列的对*象交互
    角色
  1. AbstractMediator(抽象中介者):
    抽象中介者定义了与各个同事对象通信的接口,通常会包含一组方法,这些方法用于注册同事对象、通知同事对象以及处理它们之间的交互请求。
    抽象中介者定义了同事类之间交互的抽象规则,允许具体中介者来实现这些交互逻辑。
  2. ConcreteMediator(具体中介者):
    具体中介者实现了抽象中介者所声明的接口,并且负责协调和管理同事对象之间的交互。
    具体中介者了解并存储其同事对象的引用,并根据需要调用它们的方法以响应来自其他同事对象的请求或事件。
  3. Colleague(同事类):
    同事类是参与交互的对象,它们拥有对中介者的引用,并通过中介者进行相互通信,而不是直接与其他同事类通信。
    同事类可以将消息发送给中介者,并可能通过中介者接收到来自其他同事类的消息。
  • 20. 外观模式:当需要为客户端提供一个统一的接口来访问子系统中的一群接口时,可以使用外观模式来简化客户端与子系统之间的交互。

总结:

  • 外观模式(Facade Pattern)是一种结构设计模式,它为子系统中的一组接口提供了一个统一的、更高级别的接口。通过这个简化后的接口,客户端可以更方便地与子系统交互,而无需了解子系统的复杂内部实现细节。

角色

  1. Facade(外观类):
  • 提供了一个更高层次的接口,该接口对子系统中的多个类进行封装和整合。
    外观类通常包含对子系统对象的引用,并定义一组方法来调用这些子系统的功能。
    客户端只需要与外观类交互,就可以完成对整个子系统的操作。
  1. Subsystem Classes(子系统类):
  • 子系统类是实际负责执行任务的对象或组件,它们共同构成了子系统。
    子系统类通常有复杂的内部结构和相互依赖关系,但这些细节对于外观类以及使用外观类的客户端来>说都是透明的
// 子系统类(Subsystem Classes)
interface MediaPlayer {
    void play();
}

interface CDPlayer extends MediaPlayer {
    void insertCD(String cdTitle);
    void ejectCD();
}

interface Tuner {
    void turnOn();
    void setFrequency(int frequency);
    void turnOff();
}

interface Amplifier {
    void on();
    void off();
    void setStereoSound();
    void setSurroundSound();
    void setVolume(int level);
}

class CDPlayerImpl implements CDPlayer {
    @Override
    public void insertCD(String cdTitle) {
        // 实现插入CD的操作
    }

    @Override
    public void ejectCD() {
        // 实现弹出CD的操作
    }

    @Override
    public void play() {
        // 实现播放CD的操作
    }
    
    // 其他相关方法...
}

// 同样实现其他子系统类如TunerImpl、AmplifierImpl等...

// 外观类(Facade)
class HomeTheaterFacade {
    private CDPlayer cdPlayer;
    private Tuner tuner;
    private Amplifier amplifier;

    public HomeTheaterFacade(CDPlayer cdPlayer, Tuner tuner, Amplifier amplifier) {
        this.cdPlayer = cdPlayer;
        this.tuner = tuner;
        this.amplifier = amplifier;
    }

    public void playCD(String cdTitle) {
        cdPlayer.insertCD(cdTitle);
        cdPlayer.play();
        amplifier.on();
        amplifier.setStereoSound();
        tuner.turnOn();
        tuner.setFrequency(99.1);  // 设置FM调频频率
    }

    public void stop() {
        cdPlayer.stop();
        tuner.turnOff();
        amplifier.off();
    }

    // 其他组合操作方法...
}

// 示例用法
public class FacadePatternDemo {
    public static void main(String[] args) {
        CDPlayer cdPlayer = new CDPlayerImpl();
        Tuner tuner = new TunerImpl();
        Amplifier amplifier = new AmplifierImpl();

        HomeTheaterFacade homeTheater = new HomeTheaterFacade(cdPlayer, tuner, amplifier);

        homeTheater.playCD("My Favorite Album");  // 简单地调用一个方法即可启动整个音乐播放流程
    }
}
  • 21. 代理模式:在系统中,我们可以使用代理模式来控制对敏感信息的访问,比如用户的个人信息,可以通过代理对象来进行访问控制。

角色

  1. Subject 抽象主题角色:这是一个接口或者抽象类,声明了真实主题和代理主题共同的方法
  2. RealSubject(真实主题角色):也称为“被代理角色”,它是代理所代表的真实对象。
  3. Proxy(代理角色):
  • 代理实现了与真实主题相同的接口(即 Subject),并可以附加额外的功能,如预处理请求、延迟加载、权限控制等。
  • 代理维护对真实主题的引用,在适当时机调用真实主题的方法来执行实际任务。
  • 在某些情况下,代理可能会对客户端请求进行拦截、过滤或增强后转发给真实主题。
  1. Client(客户端)
  • 客户端通过 Subject 接口与代理或真实主题交互,无需关心与之交互的对象是代理还是真实主题。

总结

  • 代理模式的核心思想是通过引入代理对象来间接访问目标对象,从而在访问过程中添加额外的操作或控制。这种模式在软件开发中有广泛应用,比如数据库连接池、远程服务调用、缓存代理、日志记录代理、权限控制代理等等。
  • 关注一下JDK动态代理(基于反射)和CGLIB代理(基于字节码技术)
  • 22. 责任链模式:当系统中需要处理一系列的请求,并且每个请求可能由不同的处理者来处理时,可以使用责任链模式来实现请求的传递和处理。

角色

  1. 抽象处理这Handler:
    • 定义了一个处理请求的接口,通常包含一个或多个方法来处理请求。
    • 通常会定义一个setNextHandler()方法用于将下一个处理者对象链接起来形成链式结构,并且包含一个对下一个处理者的引用。
    • 可能还包含一个抽象的或通用的处理请求的方法,比如handleRequest(Request request)。
  2. ConcreteHandler(具体处理者)
    • 继承自抽象处理者并实现了处理请求的方法。
    • 每个具体处理者在其内部决定是否能够处理当前请求。如果可以处理,则执行相应的逻辑;如果不可以处理,则通过调用其内部持有的下一个处理者的相同方法,将请求传递给下一个节点。
  3. Request(请求):
    • 请求对象封装了客户端发出的具体请求信息,它会被沿着责任链传递
  4. Client(客户端)
    • 创建责任链,并向链中的第一个处理者提交请求
    • 客户端并不关心请求是如何被处理和在链中如何传递的,它只需要知道请求最终会被合适的处理者处理即可。
// 请求对象(Request)
class LeaveRequest {
    private String employeeName;
    private int leaveDays;

    public LeaveRequest(String employeeName, int leaveDays) {
        this.employeeName = employeeName;
        this.leaveDays = leaveDays;
    }

    // 其他获取属性的方法...

    @Override
    public String toString() {
        return "Leave Request from " + employeeName + " for " + leaveDays + " days";
    }
}

// 抽象处理者(Handler)
abstract class Approver {
    protected Approver nextApprover;  // 对下一个处理者的引用

    public void setNextApprover(Approver approver) {
        this.nextApprover = approver;
    }

    public abstract void processRequest(LeaveRequest request);
}

// 具体处理者(ConcreteHandler)
class Manager extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getLeaveDays() <= 3) {  // 假设经理可以审批3天以内的假期
            System.out.println("Manager approved the request: " + request);
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);  // 将请求转发给上级领导
        } else {
            System.out.println("No one can approve this request.");
        }
    }
}

class Director extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getLeaveDays() <= 10) {  // 假设总监可以审批10天以内的假期
            System.out.println("Director approved the request: " + request);
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);  // 转发给更高级别的领导
        } else {
            System.out.println("No one can approve this request.");
        }
    }
}

// 客户端(Client)
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        Manager manager = new Manager();
        Director director = new Director();

        manager.setNextApprover(director);  // 构建责任链

        LeaveRequest request1 = new LeaveRequest("Employee A", 2);
        LeaveRequest request2 = new LeaveRequest("Employee B", 5);
        LeaveRequest request3 = new LeaveRequest("Employee C", 15);

        manager.processRequest(request1);  // 经理审批
        manager.processRequest(request2);  // 经理不能审批,转给总监
        manager.processRequest(request3);  // 经理和总监都不能审批
    }
}
  • 23. 享元模式:电商系统通常需要管理大量商品,每个商品可能有多个属性和规格(比如颜色、尺码等),而这些属性和规格可能是可以共享的。

预览:

  • 享元模式(Flyweight Pattern)是一种结构型设计模式,其主要目的是通过共享已经存在的对象来大幅度减少创建大量相似对象所消耗的内存资源。

角色

  1. Flyweight 抽象享元类:
    • 定义了所有具体享元类需要实现的公共接口。这个接口通常包含了可以共享的部分状态和方法。
  2. ConcreteFlyweight具体享元类:
  3. UnsharedConcreteFlyweight 不可共享的享元类:
    • 在某些情况下,不是所有的享元都可以共享。这种类不参与共享池的管理,每个实例都包含独特的信息,不能被其他对象共享。
  4. FlyweightFactory 享元工厂: 负责创建和管理享元对象,确保合理的享元对象复用。
  5. Client:
    • 使用享元对象的外部状态,并通过享元工厂获取所需的具体享元对象。
    • 客户端并不直接创建具体的享元对象,而是通过享元工厂间接访问它们

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1389782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

红米手机录屏功能在哪?这里有你想要的答案

“有人知道红米手机录屏功能在哪吗&#xff1f;刚买了最新款的红米K70&#xff0c;本来打算用来录制游戏&#xff0c;可是找了半天&#xff0c;就是没看见录屏功能&#xff0c;真的很着急&#xff0c;有没有大佬教教我。” 在手机成为人们生活不可或缺的一部分的今天&#xff…

市场下行,中国半导体进口数量、金额双双两位数锐减 | 百能云芯

根据中国海关总署最新统计&#xff0c;2023年中国累计进口集成电路&#xff08;半导体晶圆&#xff09;数量为4795亿颗&#xff0c;较2022年下降10.8%&#xff1b;而进口金额为3494亿美元&#xff0c;下降15.4%。这一数据显示&#xff0c;中国半导体进口在数量和金额两方面均出…

基于域账户及西门子simatic logon的集中权限管理的实现

原创 Luis Wang 智能大大号引文&#xff1a;博途工控人平时在哪里技术交流博途工控人社群 西门子在工业自动化领域可谓傲视群雄&#xff0c;在制药工厂&#xff0c;有超过50%以上的自动化系统、设备都配备了西门子的PLC、DCS、HMI及SCADA(wincc)平台&#xff1b;包括配液及CIP…

Arya碎碎念 | 2023年编程之旅,2024年代码人生展望

前言 回顾过去这一年&#xff0c; 2023年编程之旅&#xff0c;2024年代码人生展望 目录 前言回望2023写博客的缘起写博客的成就参加的创作活动产出的优质博客文章 展望2024代码开发方面博客规划方面 另外另外我有了一直喵 总结 回望2023 写博客的缘起 3年前&#xff0c;注册…

JMeter 源码解读HashTree

背景&#xff1a; 在 JMeter 中&#xff0c;HashTree 是一种用于组织和管理测试计划元素的数据结构。它是一个基于 LinkedHashMap 的特殊实现&#xff0c;提供了一种层次结构的方式来存储和表示测试计划的各个组件。 HashTree 的特点如下&#xff1a; 层次结构&#xff1a;Ha…

一键完成爬虫之Cookie获取:利用浏览器模拟一个cookie出来、面对反爬虫、加密的cookie的应对方法

一键完成爬虫之Cookie获取&#xff1a;利用浏览器模拟一个cookie出来、面对反爬虫、加密的cookie的应对方法 本文提供一个快速取得cookie的办法&#xff0c;用来应对一些网站的的反爬虫和cookie失效等情况本接口是收费的&#xff08;1分钱1次调用&#xff0c;不愿付费自行折腾…

flutter使用get依赖实现全局loading效果,弹窗loading状态

get dialog的官网文档&#xff1a;GetDialogRoute class - dialog_route library - Dart API 可以使用Get.dialog()方法来创建一个自定义的加载弹窗&#xff0c;get框架是支持自定义弹窗效果的&#xff0c;所以我们就使用这个方式来自定义一个弹窗效果&#xff0c;并且点击遮罩…

curl 测试返回状态码

curl 测试返回状态码 curl -I -m 10 -o /dev/null -s -w %{http_code} www.baidu.com -I 仅测试HTTP头 -m 10 最多查询10s -o /dev/null 屏蔽原有输出信息 -s silent -w %{http_code} 控制额外输出 测试&#xff1a; curl -I -m 10 -o /dev/null -s -w %{http_code} www.baid…

【上分日记】第379场周赛(分类讨论 + 数学 + 前缀和)

文章目录 前言正文1.3000. 对角线最长的矩形的面积2.3001. 捕获黑皇后需要的最少移动次数3.3002. 移除后集合的最多元素数3.3003. 执行操作后的最大分割数量 总结尾序 前言 终于考完试了&#xff0c;考了四天&#xff0c;也耽搁了四天&#xff0c;这就赶紧来补这场周赛的题了&a…

解决kali beef启动失败解问题

只限于出现这个提示的时候使用 卸载 ruby apt remove ruby 卸载 beef apt remove beef-xss 重新安装ruby apt-get install ruby apt-get install ruby-dev libpcap-dev gem install eventmachine 重新安装beef apt-get install beef-xss 弄完以上步骤如果还是不行就重启kali再试…

SpringBoot集成p6spy

P6Spy 是一个可以用来在应用程序中拦截和修改数据操作语句的开源框架。 通过 P6Spy 我们可以对 SQL 语句进行拦截,相当于一个 SQL 语句的记录器,这样我们可以用它来作相关的分析,比如性能分析。这里主要用于在控制台打印SQL时能自动将问号替换成实际参数打印一个可执行的SQL…

原子累加器 LongAdder

&#x1f47d;System.out.println(“&#x1f44b;&#x1f3fc;嗨&#xff0c;大家好&#xff0c;我是代码不会敲的小符&#xff0c;双非大四&#xff0c;Java实习中…”); &#x1f4da;System.out.println(“&#x1f388;如果文章中有错误的地方&#xff0c;恳请大家指正&a…

nginx基本优化

安装nginx隐藏版本号 查看百度web服务器 [rootcjq11 ~]# curl -I http://www.baidu.com 隐藏nginx服务器版本号 [rootcjq11 ~]# cd /usr/local/src/nginx-1.22.0/ [rootcjq11 nginx-1.22.0]# vim src/core/nginx.h第13、14行修改版本号和服务器名称 [rootcjq11 nginx-1.2…

Springboot开发的大学生寝室考勤系统刷脸进出宿舍系统源码有论文

主要功能&#xff1a; 学生可以申请换寝&#xff0c;申请宿舍维修&#xff0c;健康上报&#xff0c;寝室长可上报寝室考勤和补签考勤&#xff08; 正常签到&#xff0c;不在寝室&#xff0c;晚归&#xff09;&#xff0c;查看寝室通报&#xff0c;公告等。 宿管处需要学生刷脸进…

Android Studio 项目结构

manifests&#xff1a;用于存放安卓程序的配置文件 AndroidManifest.xml&#xff1a;这是Android应用程序的清单文件&#xff0c;包含了应用程序的基本信息和组件声明等java&#xff1a;Java源代码文件存放的根目录 主代码 com.example.app&#xff1a;应用程序的主包名&#x…

Matlab:isomorphism

语法&#xff1a; P isomorphism(G1,G2) %计算图G1和G2之间的图同构等价关系&#xff08;如果存在&#xff09;。若不存在同构&#xff0c;则P为空数组 P isomorphism(___,Name,Value) %使用一个或多个名称-值对组参数指定其他选项 [P,edgeperm] isomorph…

浅谈SQL优化

避免使用子查询 例&#xff1a; select * from t1 where id in (select id from t2 where name lolly1023);其子查询在MySQL5.5版本里&#xff0c;内部执行计划是&#xff1a;先查询外表再匹配内表&#xff0c;而不是先查内表t2&#xff0c;当外表的数据很大时&#xff0c;查…

VM安装群晖系统 挂载整个硬盘给群晖系统

前言 在我们日常业务需求中&#xff0c;经常需要把整个磁盘的空间分配给群晖使用&#xff0c;那么如何通过vm分配整个磁盘空间给群晖系统。 操作 需要用管理员运行VM虚拟机 然后添加硬盘 就可以有权限全部添加了。这样会清除要挂载的磁盘的全部的数据。

蓝莓产量预测(R语言版)

数据描述 字段名 描述 字段名 描述 id 蓝莓唯一标识 MinOfUpperTRange 花期内最高温带日平均气温的最低记录, Clonesize 蓝莓克隆平均大小 AverageOfUpperTRange 花期内最高温带日平均气温, Honeybee 蜜蜂密度 MaxOfLowerTRange 花期内最低温带日平均气温的最…

vscode显示120字符或者80字符提示线或者显示垂直标尺

vscode显示120字符或者80字符提示线或者显示垂直标尺 一般规定一行代码不超过80或者120个字符。取决于团队的编码规范。 不同公司不同团队有不同的规定。 当单行代码过长。产生横向滚动条。使得代码难以阅读。 打开全局设置的settings.json /C:/Users/xxx/AppData/Roaming/Cod…