设计模式之结构型模式及其相应代码:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式

本文介绍了结构型设计模式,包括适配器模式的类适配器和对象适配器形式,装饰器模式在不改变对象结构的情况下增加新功能,代理模式控制对真实对象的访问,以及外观模式提供子系统的统一接口,桥接模式解耦抽象和实现,组合模式处理对象树结构,享元模式通过共享减少对象创建。这些模式有助于构建灵活、可扩展的软件系统。
摘要由CSDN通过智能技术生成

结构型模式

用于解决在系统设计中常见的对象之间的关系和组织的问题。这些模式通过定义不同对象之间的接口、关联、聚合和继承关系,帮助我们构建更灵活、可复用、可维护的软件系统。

适配器模式

作用:使原本由于接口不兼容而不能一起工作的类可以协同工作。
适配器模式的核心思想是引入一个适配器,它充当两个不兼容接口之间的桥梁。适配器实现了客户端所期望的目标接口,并在内部包含了对于不兼容接口的引用。

类适配器模式

类适配器模式通过多重继承来适配一个类到另一个接口。适配器类继承了目标接口,同时又继承了被适配者类,从而将目标接口和被适配者类联系起来。适配器类在实现目标接口方法时,调用被适配者类的方法来实现适配。

public interface Target {
    void request();
}

public class Adaptee {
    public void specificRequest() {
        System.out.println("Adaptee: specificRequest");
    }
}
// 创建适配器,同时继承被适配者的类,又实现目标接口,使二者建立联系
public class Adapter extends Adaptee implements Target {
    @Override
    public void request() {
        specificRequest();
    }
}

// 用户端使用适配器
public class Client {
    public static void main(String[] args) {
        Target target = new Adapter();
        // request()方法调用了Adaptee类的specificRequest()方法
        // 从而来实现适配。
        target.request(); 
    }
}
对象适配器模式

对象适配器模式通过组合来适配一个类到另一个接口。适配器类中包含一个被适配者类的实例,通过调用被适配者类的方法来实现适配。

public interface Target {
    void request();
}

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

public class Adapter implements Target {
    private Adaptee adaptee;

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

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

// 调用适配器
public class Client {
    public static void main(String[] args) {
        Adaptee adaptee = new Adaptee();
        Target target = new Adapter(adaptee);
        // 调用适配后的接口方法
        target.request(); 
    }
}

装饰器模式

作用:允许向一个现有的对象添加新的功能,同时又不改变其结构。
原理:创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

// 抽象组件
public interface Component {
    void operation();
}

// 具体组件
public class ConcreteComponent implements Component {
    public void operation() {
        System.out.println("执行原始操作");
    }
}

// 抽象装饰器
public abstract class Decorator implements Component {
    protected Component component;

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

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

// 具体装饰器
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        // 增加新的行为
        addBehavior();
    }

    private void addBehavior() {
        System.out.println("执行额外行为");
    }
}

// 使用装饰器模式
public class Main {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component decoratedComponent = new ConcreteDecorator(component);
        decoratedComponent.operation();
    }
}

代理模式

作用:通过代理对象来控制对实际对象的访问。
原理:核心是代理类,它与实际对象实现相同的接口,并持有一个实际对象的引用。代理类负责在调用时对实际对象进行管理和控制,可以在调用实际对象的方法前后添加额外的逻辑。

// 抽象主题接口
interface Subject {
    void request();
}

// 真实主题
class RealSubject implements Subject {
    public void request() {
        System.out.println("执行真实主题的请求");
    }
}

// 代理类
class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy() {
        this.realSubject = new RealSubject();
    }

    public void request() {
        System.out.println("代理类处理请求");
        this.realSubject.request();
    }
}

// 使用代理模式
public class Client {
    public static void main(String[] args) {
        Subject proxy = new Proxy();
        proxy.request();
    }
}

外观模式

作用:为复杂子系统提供了一个简单统一的接口,使得客户端可以更方便地与子系统进行交互,同时也将子系统与客户端解耦。
原理:通过引入一个外观类,封装了一组相关的子系统接口,提供了一个高层次的接口供客户端使用。客户端只需要与外观类进行交互,不需要直接与子系统的多个类进行交互,从而简化了客户端的调用操作。

// 子系统类
class MusicPlayer {
    public void playSong(String song) {
        System.out.println("播放音乐:" + song);
    }
}

class VideoPlayer {
    public void playVideo(String video) {
        System.out.println("播放视频:" + video);
    }
}

class SubtitleDisplay {
    public void displaySubtitle(String video) {
        System.out.println("显示字幕:" + video);
    }
}

// 外观类
class AudioPlayer {
    private MusicPlayer musicPlayer;
    private VideoPlayer videoPlayer;
    private SubtitleDisplay subtitleDisplay;

    public AudioPlayer() {
        musicPlayer = new MusicPlayer();
        videoPlayer = new VideoPlayer();
        subtitleDisplay = new SubtitleDisplay();
    }

    // 对外提供的高层次接口
    public void playMusic(String song) {
        musicPlayer.playSong(song);
    }

    public void playVideo(String video) {
        videoPlayer.playVideo(video);
        subtitleDisplay.displaySubtitle(video);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();
        // 直接通过外观调用
        audioPlayer.playMusic("Yesterday");
        audioPlayer.playVideo("Avatar");
    }
}

桥接模式

作用:将抽象部分与实现部分分离,使得它们可以独立地变化。
原理:创建一个桥接接口,将抽象部分和实现部分解耦。抽象部分通过桥接接口调用实现部分,从而实现了抽象和实现的解耦,使得它们可以独立地进行扩展和变化。

// 抽象部分
abstract class Shape {
    protected DrawingAPI drawingAPI;

    protected Shape(DrawingAPI drawingAPI) {
        this.drawingAPI = drawingAPI;
    }

    public abstract void draw();
}

// 扩展抽象部分
class LineShape extends Shape {
    public LineShape(DrawingAPI drawingAPI) {
        super(drawingAPI);
    }

    public void draw() {
        System.out.println("绘制直线");
        drawingAPI.draw();
    }
}

class CircleShape extends Shape {
    public CircleShape(DrawingAPI drawingAPI) {
        super(drawingAPI);
    }

    public void draw() {
        System.out.println("绘制圆形");
        drawingAPI.draw();
    }
}

// 实现部分
interface DrawingAPI {
    void draw();
}

// 具体实现部分
class DirectXAPI implements DrawingAPI {
    public void draw() {
        System.out.println("使用DirectX绘图API");
    }
}

class OpenGLAPI implements DrawingAPI {
    public void draw() {
        System.out.println("使用OpenGL绘图API");
    }
}

// 使用桥接模式代码
public class Client {
    public static void main(String[] args) {
        DrawingAPI directx = new DirectXAPI();
        DrawingAPI opengl = new OpenGLAPI();

        Shape lineShape = new LineShape(directx);
        lineShape.draw();

        Shape circleShape = new CircleShape(opengl);
        circleShape.draw();
    }
}

组合模式

作用:组合模式可以使客户端统一对待单个对象和组合对象,从而使得用户可以一致地使用单个对象和组合对象,降低了使用对象树结构的复杂性。
原理:组件 + 叶子组件 + 容器组件

// 实现一个文件系统的树形结构,包括文件和文件夹两种类型的节点:

// 组件接口
interface FileSystemComponent {
    void printStructure();
}

// 叶子组件:文件
class File implements FileSystemComponent {
    private String name;

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

    public void printStructure() {
        System.out.println("文件: " + name);
    }
}

// 容器组件:文件夹
class Folder implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> components;

    public Folder(String name) {
        this.name = name;
        components = new ArrayList<>();
    }

    public void addComponent(FileSystemComponent component) {
        components.add(component);
    }

    public void removeComponent(FileSystemComponent component) {
        components.remove(component);
    }

    public void printStructure() {
        System.out.println("文件夹: " + name);
        for (FileSystemComponent component : components) {
            component.printStructure();
        }
    }
}

// 使用组合模式
public class Client {
    public static void main(String[] args) {
        FileSystemComponent file1 = new File("file1.txt");
        FileSystemComponent file2 = new File("file2.txt");
        FileSystemComponent file3 = new File("file3.txt");

        FileSystemComponent folder1 = new Folder("folder1");
        folder1.addComponent(file1);
        folder1.addComponent(file2);

        FileSystemComponent folder2 = new Folder("folder2");
        folder2.addComponent(file3);

        FileSystemComponent root = new Folder("root");
        root.addComponent(folder1);
        root.addComponent(folder2);
        
        root.printStructure();
    }
}

享元模式

作用:通过共享对象,以提高系统的性能和减少内存消耗。
原理:将对象分为可共享(内部状态)和不可共享(外部状态)的部分,通过共享内部状态来减少对象的创建和存储。

// 抽象享元接口
interface ChessPiece {
    void draw(int x, int y);
}

// 具体享元类:白色棋子
class WhiteChessPiece implements ChessPiece {
    private String color;

    public WhiteChessPiece() {
        this.color = "白色";
    }

    public void draw(int x, int y) {
        System.out.println(color + "棋子,位置:(" + x + ", " + y + ")");
    }
}

// 具体享元类:黑色棋子
class BlackChessPiece implements ChessPiece {
    private String color;

    public BlackChessPiece() {
        this.color = "黑色";
    }

    public void draw(int x, int y) {
        System.out.println(color + "棋子,位置:(" + x + ", " + y + ")");
    }
}

// 享元工厂类
class ChessPieceFactory {
    private HashMap<String, ChessPiece> chessPieces;

    public ChessPieceFactory() {
        chessPieces = new HashMap<>();
    }

    public ChessPiece getChessPiece(String color) {
        if (chessPieces.containsKey(color)) {
            return chessPieces.get(color);
        } else {
            ChessPiece chessPiece;
            if (color.equals("白色")) {
                chessPiece = new WhiteChessPiece();
            } else {
                chessPiece = new BlackChessPiece();
            }
            chessPieces.put(color, chessPiece);
            return chessPiece;
        }
    }
}

// 使用享元模式
public class Client {
    public static void main(String[] args) {
        ChessPieceFactory factory = new ChessPieceFactory();

        ChessPiece whitePiece1 = factory.getChessPiece("白色");
        whitePiece1.draw(0, 0);

        ChessPiece blackPiece1 = factory.getChessPiece("黑色");
        blackPiece1.draw(0, 1);

        ChessPiece whitePiece2 = factory.getChessPiece("白色");
        whitePiece2.draw(1, 0);
        
        // 输出结果:
        // 白色棋子,位置:(0, 0)
        // 黑色棋子,位置:(0, 1)
        // 白色棋子,位置:(1, 0)
    }
}

其他设计模式及其代码

创建型设计模式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值