GoF设计模式——结构型设计模式分析与应用
文章目录
- UML图的结构主要表现为:继承(抽象)、关联 、组合或聚合 的三种关系。
- 1. 继承(抽象,泛化关系)
- 2. 关联
- 3. 组合/聚合
- 各种可能的配合:
- 1. 关联后抽象
- 2. 关联的集合
- 3. 组合接口
- 4. 递归聚合接口
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
GoF(Gang of Four)设计模式的三大类:
- 创建型设计模式(Creational Patterns)
- 结构型设计模式(Structural Patterns)
- 行为设计模式(Behavioral Patterns)
Object Scope 可用于运行时
Class Scope 只能用于编译时
UML图的结构主要表现为:继承(抽象)、关联 、组合或聚合 的三种关系。
车是交通工具,车是我的,车里有发动机
1. 继承(抽象,泛化关系)
class Vehicle {
String name;
void move() {}
}
class Car extends Vehicle {
void drive() {}
}
2. 关联
class Person {
Car car; // 关联关系
}
class Car {
String model;
}
3. 组合/聚合
class Car {
Engine engine; // 组合关系
GPS gps; // 聚合关系
}
class Engine {}
class GPS {}
各种可能的配合:
圈住部分即为原因。
1. 关联后抽象
2. 关联的集合
3. 组合接口
4. 递归聚合接口
这里递归怎么理解?
其实是虽然我的装饰器实现了这个接口,但是我的装饰器类内部成员可能还有有这个接口类。
Adapter
适配器模式能够将不兼容的接口转换成兼容的接口,从而使得原本无法直接交互的类能够合作。
可以在不修改现有代码的情况下,重用第三方的功能或代码。
可以在不同的系统间进行灵活的接口转换,尤其适用于系统集成和迁移。
Adapter(适配器)设计模式
继承+关联 (“关联后抽象”)
“ 加一层,新接口。”
(“R”标记:可运行时改变;实心箭头指实现,空心指泛化)
设计逻辑的层次:
- 先从具体类(ConcreteAdapter)的实现入手,明确其与其他类的关联(如 Adaptee)。
- 然后在其上进一步抽象出一个统一的接口(Adapter),以适应多种实现需求。
// 老版本的播放器接口
class OldMediaPlayer {
void playAudio() {
System.out.println("Playing audio...");
}
}
// 新播放器接口
interface ModernPlayer {
void play();
}
// 适配器类
class PlayerAdapter implements ModernPlayer {
private OldMediaPlayer oldMediaPlayer;
public PlayerAdapter(OldMediaPlayer oldMediaPlayer) {
this.oldMediaPlayer = oldMediaPlayer;
}
@Override
public void play() {
oldMediaPlayer.playAudio(); // 使用旧方法适配新接口
}
}
// 客户端代码
public class AdapterExample {
public static void main(String[] args) {
OldMediaPlayer oldPlayer = new OldMediaPlayer();
ModernPlayer modernPlayer = new PlayerAdapter(oldPlayer);
modernPlayer.play(); // 使用新接口播放
}
}
Bridge
解耦抽象和实现:桥接模式将抽象部分与实现部分分离,可以独立地扩展两者。
新增抽象层或者实现层时,不会影响到对方,增强了系统的可扩展性。
避免重复代码,增加代码复用性。
Bridge(桥)设计模式
组合接口
“ 比如形状类里加个颜色类。 而该形状可以在各种地方使用”
// 实现接口
interface Color {
String fill();
}
class Red implements Color {
public String fill() {
return "Color is Red";
}
}
class Blue implements Color {
public String fill() {
return "Color is Blue";
}
}
// 抽象类
abstract class Shape {
protected Color color;
public Shape(Color color) {
this.color = color;
}
abstract void draw();
}
class Circle extends Shape {
public Circle(Color color) {
super(color);
}
public void draw() {
System.out.println("Drawing Circle. " + color.fill());
}
}
// 客户端代码
public class BridgeExample {
public static void main(String[] args) {
Shape redCircle = new Circle(new Red());
Shape blueCircle = new Circle(new Blue());
redCircle.draw();
blueCircle.draw();
}
}
Composite
树形结构:组合模式允许你以树形结构来组合对象,简化了对象的管理和处理。
统一操作:可以统一对单个对象和组合对象的处理,客户端不需要知道是单一对象还是组合对象。
递归结构:支持递归组合,使得层次结构更易于表示和管理,特别适用于有层次结构的对象模型。
Composite(组合)设计模式
递归聚合接口
“可以都放进一个容器,装满书的书包”
书包里可能还有一个书包,所以书包的“聚合”里,还有component抽象类——递归。
// 组件接口
interface Component {
void operation();
}
// 叶子节点
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
public void operation() {
System.out.println("Leaf: " + name);
}
}
// 容器节点
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
// 客户端代码
public class CompositeExample {
public static void main(String[] args) {
Composite root = new Composite();
Leaf leaf1 = new Leaf("Leaf 1");
Leaf leaf2 = new Leaf("Leaf 2");
Composite subTree = new Composite();
subTree.add(new Leaf("SubTree Leaf 1"));
root.add(leaf1);
root.add(leaf2);
root.add(subTree);
root.operation(); // 遍历树形结构
}
}
Decorator
动态扩展功能:装饰器模式可以在运行时动态地给对象添加新的功能,而不改变原有类的代码。
增加灵活性:通过装饰器,可以为对象添加多种功能,客户端可以根据需求进行组合,增加了系统的灵活性。
符合开放/关闭原则:装饰器通过扩展功能,而不是修改类本身,符合开放/关闭原则。
Decorator(装饰器)设计模式
递归聚合接口
“对不同物品可以进行不同装饰”
“两组抽象和实现。
装饰器里有【具体部件】和新的方法”
// 抽象组件(饮料)
interface Beverage {
String getDescription();
double cost();
}
// 具体组件
class Coffee implements Beverage {
public String getDescription() {
return "Coffee";
}
public double cost() {
return 5.0;
}
}
// 装饰器
abstract class AddOnDecorator implements Beverage {
protected Beverage beverage;
public AddOnDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
class Milk extends AddOnDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
public double cost() {
return beverage.cost() + 1.0;
}
}
class Sugar extends AddOnDecorator {
public Sugar(Beverage beverage) {
super(beverage);
}
public String getDescription() {
return beverage.getDescription() + ", Sugar";
}
public double cost() {
return beverage.cost() + 0.5;
}
}
// 客户端代码
public class DecoratorExample {
public static void main(String[] args) {
Beverage beverage = new Coffee();
beverage = new Milk(beverage);
beverage = new Sugar(beverage);
System.out.println(beverage.getDescription() + " costs " + beverage.cost());
}
}
Facade
简化接口:外观模式为复杂子系统提供了一个统一的、高层的接口,简化了客户端的调用方式。
降低耦合:客户端不需要了解各个子系统的实现细节,只需要与外观类交互,从而降低了系统的耦合度。
便于扩展:如果需要修改子系统的实现,可以在外观类中进行修改,而不影响客户端代码。
Façade(门面)设计模式
关联的集合
“将各个组件集成在一起”
class CPU {
public void start() {
System.out.println("CPU started.");
}
}
class Memory {
public void load() {
System.out.println("Memory loaded.");
}
}
class HardDrive {
public void readData() {
System.out.println("HardDrive read data.");
}
}
// 门面类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void start() {
cpu.start();
memory.load();
hardDrive.readData();
}
}
// 客户端代码
public class FacadeExample {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.start(); // 一键启动
}
}
Flyweight
内存优化:享元模式通过共享相同的对象实例,减少了内存的消耗,尤其适用于大量相似对象的场景。
提高性能:由于共享对象的使用,可以减少对象的创建和销毁,提高了系统的性能。
Flyweight(享元)设计模式
关联的集合
“共享的懒汉模式”
// 抽象享元
interface Shape {
void draw();
}
// 具体享元
class Circle implements Shape {
private String color;
public Circle(String color) {
this.color = color;
}
public void draw() {
System.out.println("Drawing " + color + " Circle");
}
}
// 享元工厂
class ShapeFactory {
private static Map<String, Shape> shapeMap = new HashMap<>();
public static Shape getCircle(String color) {
if (!shapeMap.containsKey(color)) {
shapeMap.put(color, new Circle(color));
System.out.println("Created new " + color + " Circle");
}
return shapeMap.get(color);
}
}
// 客户端代码
public class FlyweightExample {
public static void main(String[] args) {
Shape redCircle = ShapeFactory.getCircle("Red");
Shape blueCircle = ShapeFactory.getCircle("Blue");
Shape anotherRedCircle = ShapeFactory.getCircle("Red");
redCircle.draw();
blueCircle.draw();
anotherRedCircle.draw(); // 复用红色圆
}
}
Proxy
控制访问:代理模式可以控制对真实对象的访问,例如延迟加载、权限控制、缓存等。
增强功能:代理类可以为目标对象增加额外的功能,比如日志记录、安全控制等,而不需要修改目标对象的代码。
降低耦合:代理类和目标类相互独立,客户端通过代理类访问目标对象,减少了对目标类的直接依赖。
Proxy(代理)设计模式
关联后抽象
“懒汉模式”
// 抽象接口
interface Image {
void display();
}
// 真实类
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading " + fileName);
}
public void display() {
System.out.println("Displaying " + fileName);
}
}
// 代理类
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName); // 延迟加载
}
realImage.display();
}
}
// 客户端代码
public class ProxyExample {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display(); // 加载并显示
image.display(); // 再次显示,无需加载
}
}