结构型模式
用于解决在系统设计中常见的对象之间的关系和组织的问题。这些模式通过定义不同对象之间的接口、关联、聚合和继承关系,帮助我们构建更灵活、可复用、可维护的软件系统。
适配器模式
作用:使原本由于接口不兼容而不能一起工作的类可以协同工作。
适配器模式的核心思想是引入一个适配器,它充当两个不兼容接口之间的桥梁。适配器实现了客户端所期望的目标接口,并在内部包含了对于不兼容接口的引用。
类适配器模式
类适配器模式通过多重继承来适配一个类到另一个接口。适配器类继承了目标接口,同时又继承了被适配者类,从而将目标接口和被适配者类联系起来。适配器类在实现目标接口方法时,调用被适配者类的方法来实现适配。
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)
}
}