便于理解的设计模式(结构型模式)【持续更新中】

结构型模式(Structural Patterns):用于处理类和对象的组合,包括代理模式、适配器模式、桥接模式、装饰器模式、外观模式、享元模式和组合模式。

一. 代理模式
1.解释
代理模式是一种结构型设计模式,用于控制其他对象的访问。它允许通过创建一个代理对象来间接访问另一个对象,这样可以控制对该对象的访问,例如可以台南佳额外的功能,起到保护、过滤或延迟处理的作用。
2. 用途
1)远程代理:用于在不同地址空间的对象之间进行通信,例如在网络上访问远程对象。
2)虚拟代理:用于对对象的创建和访问进行优化,例如延迟加载。
3)保护代理:用于控制对敏感对象的访问权限,例如身份验证和权限检查。
4)动态代理:在运行时创建代理对象,允许在运行时添加额外的功能。

代码示例:

// 创建接口
interface Internet{
	void connectTo(String serverHost);
}

// 创建实际对象
class RealInternet implements Internet{
	@Override
	public void connectTo(String serverHost){
		System.out.printIn("连接到:" + serverHost);
	}
}

// 创建代理对象
class ProxyInternet implements Internet{
	private internet realInternet = new RealInternet();
	// 受限制的网站地址
	private static String[] restrictedSites = {"baidu.com","baidu1.com"};
	
	@Override
	public void connectTo(String serverHost){
		// 判断是否连接成功
		if(checkAccess(serverHost)){
			realInternet.connectTo(serverHost);
		}else{
			System.out.println("访问被拒绝,无法连接到:" + serverHost);
		}
	}

	private boolean checkAccess(String serverHost){
		for(String site : restrictedSites){
			if(site.equals(serverHost)){
				return false;
			}
		}
		return true;
	}
}

// 客户端代码
public class Main{
	public static void main(String[] args){
		Internet internet = new ProxyInternet();
		
		internet.connectTo("balabala.com"); // 正常访问
		internet.connectTo("baidu.com"); // 访问被拒绝
	}
}

我们定义了 Internet 接口,表示可以连接到互联网的类。然后我们创建了实际对象 RealInternet,模拟实际连接到互联网的行为。接着我们创建了代理对象 ProxyInternet,在其中添加了对被访问网站的过滤控制。在客户端代码中,我们创建了代理对象并尝试连接到不同的网站,结果会根据代理对象的控制逻辑来执行。

在这个示例中,代理模式被用于控制对互联网的访问权限,在代理对象中进行了网站的过滤控制,从而达到保护的目的。

二. 适配器模式

例子: 考虑一个中国电器公司生产的电源适配器(220V),以便在欧洲使用中国的电子设备。这个适配器可以接受欧洲标准(非220V)的插头,并将其转换成中国标准的插头,以便中国设备可以在欧洲插座上使用。在这里,电源适配器充当了一个适配器,将欧洲标准的接口转换成了中国标准的接口。

  1. 解释
    工厂模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口。这样客户端无需修改现有代码,就可以使用特定接口的对象。

  2. 用途

  1. 在需要使用的接口和现有类的接口不匹配时,可以通过适配器模式进行转换。
  2. 在需要重用已有类,但其接口与需求不匹配时,可以使用适配器模式。

代码示例:

// 定义欧洲标准的插头接口
interface EuropeanSocket{
	void insert();
}

// 定义中国标准的插头接口
interface ChineseSocket{
	void connect();
}

// 创建现有的中国设备
class ChineseDevice implements ChineseSocket{
	@Override
	public void connect(){
		System.out.println("连接中国标准插座");
	}
}

// 创建适配器,以便中国设备可以在欧洲使用
class SocketAdapter implements EuropeanSocket{
	private ChineseSocket chineseDevice;

	public SocketAdapter(ChineseSocket chineseDevice){
		this.chineseDevice = chineseDevice;
	}

	@Override
	public void insert(){
		chineseDevice.connect();
		System.out.println("适配连接欧洲插座");
	}
}

// 客户端代码
public class Main{
	public static void main(String[] args){
		ChineseSocket chineseDevice = new ChineseDevice();
		EuropeanSocket adapter = new SocketAdapter(chineseDevice);
		// 通过适配器将中国设备插入到欧洲插座
		adapter.insert();
	}
}


在这个示例中,我们模拟了适配器模式。我们首先定义了欧洲标准的插头接口 EuropeanSocket 和中国标准的插头接口 ChineseSocket。然后创建了现有的中国设备,并定义了适配器 SocketAdapter,它接受中国标准的插头,并实现了欧洲标准的插头接口。在客户端代码中,我们创建了中国设备的实例,然后通过适配器将其插入到欧洲插座,从而实现了将中国设备适配到欧洲插座的功能。

在这个示例中,适配器模式被用于在现有的中国设备和欧洲插座之间进行适配,以便实现设备在不同标准插座上的使用。

三. 桥接模式
1.解释
桥接模式是一种设计模式,用于将抽象部分与它的实现部分分离,从而使它们可以独立地变化。这种模式涉及一个接口,它充当一个桥,使得多个实体可以作为桥梁连接。这种类型的设计模式属于结构型模式。
2.用途
1)当软件系统要在多个维度上进行扩展时,比如有多个平台、多个数据库、多个应用等,可以使用桥接模式来管理这些拓展要素。
2)当一个类存在多个变化因素,而又不希望使用类继承来处理时,可以考虑使用桥接模式。
3.示例

// 创建桥接接口
interface DrawingAPI{
	void drawCircle(double x, double y, double radius);
}

// 创建具体的实现类
class DrawingAPI01 implements DrawingAPI{
	public void drawCircle(double x, double y, double radius){
		System.out.printf("API01画的⚪在 %f:%f 半径为%f\n",x,y,radius);
	}
}


class DrawingAPI02 implements DrawingAPI{
	public void drawCircle(double x, double y, double radius){
		System.out.printf("API02画的⚪在 %f:%f 半径为%f\n",x,y,radius);
	}
}


abstract class Shape{
	protected DrawingAPI drawingAPI;

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



在这个示例中,我们使用桥接模式实现了将图形的抽象部分与其实现部分分离。我们定义了一个 DrawingAPI 接口,它充当桥梁来连接具体的实现类。然后我们创建了具体的实现类 DrawingAPI1 和 DrawingAPI2,分别表示不同的绘制API。接着我们定义了抽象类 Shape 和具体类 Circle,在其中包含了对图形的抽象描述和对图形的具体绘制操作。最后,在客户端代码中我们创建了具体的图形对象,并选择具体的绘制API来进行图形的绘制。

桥接模式能够灵活地连接抽象部分和实现部分,使得它们可以独立地变化和扩展。在示例中,我们可以轻松地添加新的绘制API和新的图形类型,而无需修改现有代码。
四. 装饰器模式
1.解释
装饰器模式是一种结构型设计模式,它允许向现有对象动态地添加新功能,而无需修改其现有代码。这种模式可以在不改变原对象结构的情况下,通过对原对象进行包装,来扩展其功能。
2.用途
1)当需要向对象添加功能,但又不希望用子类继承的方式创建大量的子类时,可以通过装饰器模式。
2)当类中的一些功能只需要在特定的情况下添加时,可以使用装饰器模式。
3.示例


// 定义一个抽象组件接口
interface Shape{
	void draw();
}

// 创建具体的组件类
class Circle implements Shape{
	public void draw(){
		System.out.println("形状:圆形");
	}
}

// 创建装饰器类
abstract class ShapeDecorator implements Shape{
	protected Shape decoratedShape;
	
	public ShapeDecorator(Shape decoratedShape){
		this.decoratedShape = decoratedShape;
	}

	public void draw(){
		decoratedShape.draw();
	}
}


// 创建具体的装饰器类
class RedShapeDecorator extends ShapeDecorator{
	public RedShapeDecorator(Shape decoratedShape){
		super(decoratedShape);
	}

	public void draw(){
		decoratedShape.draw();
		setRedBorder(decoratedShape);
	}

	private void setRedBorder(Shape decoratedShape){
		System.out.println("边框颜色:红色");
	}
}

// 客户端代码
public class Main{
	public static void main(String[] args){
		Shape circle = new Circle();
		Shape redCircle = new RedShapeDecorator(new Circle());

		System.out.println("正常的圆");
		circle.draw();

		System.out.println("\n红色边框的圆")
		redCicle.draw();
	}
}



在这个示例中,我们使用了装饰器模式来向 Shape 对象添加边框颜色的功能。我们首先定义了抽象组件 Shape 接口,并创建了具体的组件类 Circle,表示一个圆形。然后定义了装饰器类 ShapeDecorator,它实现了 Shape 接口并包含一个 decoratedShape 成员变量。接着我们创建了具体的装饰器类 RedShapeDecorator,它继承自 ShapeDecorator 并在 draw() 方法中添加了对圆形的边框颜色设置。最后在客户端代码中,我们创建了一个普通的圆形对象和一个添加了红色边框的圆形对象,通过装饰器模式来动态添加了新功能。

装饰器模式可以有效地对现有对象进行功能扩展而无需修改其原有代码,同时也能避免创建大量的子类来进行功能扩展。通过装饰器模式,我们可以在运行时动态地添加功能,使得系统更加灵活和可扩展。

五. 外观模式
1.解释
它提供了一个统一的接口(外观),用来访问子系统中的一组接口。外观模式隐藏了子系统的复杂性,并提供了一个简化的接口,以便客户端更容易地使用子系统。

2.用途
1)当一个系统有许多复杂的子系统,并且客户端需要通过一个简单统一的接口来与这些子系统进行交互时,可以使用外观模式。
2)当需要对一个复杂子系统进行重构,以减少对客户端的影响时,可以使用外观模式。
3.示例


// 子系统中的一组接口
class CPU {
    public void freeze() { 
        System.out.println("CPU: 冻结"); 
    }
    public void jump(long position) { 
        System.out.println("CPU: 跳转到 " + position); 
    }
    public void execute() { 
        System.out.println("CPU: 执行"); 
    }
}

class Memory {
    public void load(long position, byte[] data) {
        System.out.println("内存: 将数据加载到 " + position);
    }
}

class HardDrive {
    public byte[] read(long lba, int size) {
        System.out.println("硬盘驱动器: 从 " + lba + " 读取数据,长度为: " + size);
        return new byte[size];
    }
}

// 外观类,提供一个简化的接口
class ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(0, hd.read(0, 1024));
        processor.jump(0);
        processor.execute();
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

在这个示例中,我们使用外观模式来隐藏了计算机中 CPU、内存和硬盘等多个子系统的复杂性。我们首先定义了 CPU、Memory 和 HardDrive 类,这些类模拟了计算机的组件。然后我们创建了 ComputerFacade 类作为外观类,它提供了一个 start 方法来启动计算机。在 start 方法中,我们可以看到外观类隐藏了启动计算机所需要的复杂步骤,客户端只需要调用一个简单的方法即可启动整个计算机。在客户端代码中,我们创建了一个外观类的实例,并调用其 start 方法来启动计算机。

外观模式可以提供一个简单的接口来访问复杂的子系统,同时也能帮助我们隐藏系统的复杂性,从而减少了客户端的使用难度。通过外观模式,我们可以更方便地使用子系统的功能,并且能够降低对子系统的耦合度。

六. 享元模式
1.解释
它旨在减少应用程序中的内存使用,特别是当需要创建多个相似对象时。享元模式通过共享对象的方式来减少内存的使用,从而提高程序的性能和效率。
该模式的核心思想是将对象的状态分为内部状态和外部状态。内部状态存储在享元对象内部,而外部状态则由客户端代码传递给享元对象。通过这种方式,相似对象可以共享内部状态,而外部状态可以作为参数传递,从而避免了创建大量相似对象的情况。
2.用途
1)当一个应用程序需要创建大量相似对象,并且这些对象具有一些共同的内部状态时,可以使用享元模式来减少内存占用。
2)当需要对对象的状态进行分离,使得一个对象可以同时用于多个情景时,可以使用享元模式。
3.示例


// 创建享元接口
interface Shape {
    void draw(int x, int y);
}

// 创建具体享元类
class Circle implements Shape {
    private final String color;

    public Circle(String color) {
        this.color = color;
    }

    public void draw(int x, int y) {
        System.out.println("用颜色绘制圆 " + color + " 在 (" + x + ", " + y + ")");
    }
}

// 创建享元工厂类
class ShapeFactory {
    private final Map<String, Shape> circleMap = new HashMap<>();

    public Shape getCircle(String color) {
        if (circleMap.containsKey(color)) {
            return circleMap.get(color);
        } else {
            Shape circle = new Circle(color);
            circleMap.put(color, circle);
            return circle;
        }
    }
}

// 客户端代码
public class Main {
    private static final String[] colors = { "Red", "Green", "Blue", "Yellow", "Black" };

    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();

        for (int i = 0; i < 20; i++) {
            Shape circle = shapeFactory.getCircle(getRandomColor());
            circle.draw(getRandomX(), getRandomY());
        }
    }

    private static String getRandomColor() {
        return colors[(int) (Math.random() * colors.length)];
    }

    private static int getRandomX() {
        return (int) (Math.random() * 100);
    }

    private static int getRandomY() {
        return (int) (Math.random() * 100);
    }
}

在这个示例中,我们使用享元模式来绘制一些颜色不同的圆形。我们首先定义了享元接口 Shape,并创建了具体的享元类 Circle,它存储了圆形的颜色。然后我们创建了享元工厂类 ShapeFactory,它用于创建和管理享元对象。在客户端代码中,我们调用了享元工厂类的 getCircle 方法来获取圆形对象,并为这些对象指定了不同的位置,通过享元模式来减少了内存占用。

通过享元模式,我们可以在大量相似对象的情况下,以共享的方式来减少内存占用。通过共享内部状态和外部状态的方式,享元模式能够提高程序的性能和效率。

七. 组合模式
1.解释
组合模式是一种结构型设计模式,它允许我们将对象组织成树形结构,以表达“整体-部分”的层次关系。组合模式允许客户端统一处理单个对象和组合对象,而无需区分它们。

该模式包含以下几个角色:
① 组件(Component):定义了共有接口的抽象类或接口,它可以包含子组件。
② 叶子(Leaf):实现了组件接口的叶子节点对象,它没有子节点。
③ 容器(Composite):实现了组件接口的容器对象,它可以包含子节点,可以对子节点进行增删查改的操作。
④ 客户端(Client):通过组合模式来构建树形结构,并通过组件接口统一处理叶子节点和容器对象

2.用途
1)当需要创建一种“整体-部分”的层次结构,并且能够统一处理整体和部分的对象时,可以使用组合模式。
2)当希望客户端可以一致地对待单个对象和组合对象时,可以使用组合模式。
3.示例


// 定义组件接口
interface Component {
    void operation();
}

// 定义叶子节点
class Leaf implements Component {
    private String name;

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

    public void operation() {
        System.out.println("叶子节点 " + name + " 的操作");
    }
}

// 定义容器节点
class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    public Component getChild(int index) {
        return children.get(index);
    }

    public void operation() {
        System.out.println("容器操作");
        for (Component component : children) {
            component.operation();
        }
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        Component leaf1 = new Leaf("A");
        Component leaf2 = new Leaf("B");

        Component composite = new Composite();
        composite.add(leaf1);
        composite.add(leaf2);

        Component leaf3 = new Leaf("C");
        Component leaf4 = new Leaf("D");

        Component composite2 = new Composite();
        composite2.add(leaf3);
        composite2.add(leaf4);

        composite.add(composite2);

        composite.operation();
    }
}

在这个示例中,我们使用组合模式来构造树形结构。我们首先定义了组件接口 Component,并创建了叶子节点类 Leaf 和容器节点类 Composite。在客户端代码中,我们创建了叶子节点和容器节点,并通过组合模式将它们组合在一起构成一个树形结构。然后我们调用容器节点的 operation 方法来对整个树形结构进行操作。通过组合模式,我们可以以统一的方式处理叶子节点和容器节点,并构建具有层次结构的组件树。

组合模式允许我们构建树形结构,并以统一的方式处理整体和部分的对象。通过这种方式,我们可以方便地对树形结构中的节点进行操作,而无需关心它们是叶子节点还是容器节点。

八. 组合模式
1.解释
组合模式是一种结构型设计模式,它允许我们将对象组织成树形结构,以表达“整体-部分”的层次关系。组合模式允许客户端统一处理单个对象和组合对象,而无需区分它们。

该模式包含以下几个角色:
① 组件(Component):定义了共有接口的抽象类或接口,它可以包含子组件。
② 叶子(Leaf):实现了组件接口的叶子节点对象,它没有子节点。
③ 容器(Composite):实现了组件接口的容器对象,它可以包含子节点,可以对子节点进行增删查改的操作。
④ 客户端(Client):通过组合模式来构建树形结构,并通过组件接口统一处理叶子节点和容器对象

2.用途
1)当需要创建一种“整体-部分”的层次结构,并且能够统一处理整体和部分的对象时,可以使用组合模式。
2)当希望客户端可以一致地对待单个对象和组合对象时,可以使用组合模式。
3.示例


// 定义组件接口
interface Component {
    void operation();
}

// 定义叶子节点
class Leaf implements Component {
    private String name;

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

    public void operation() {
        System.out.println("叶子节点 " + name + " 的操作");
    }
}

// 定义容器节点
class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }

    public Component getChild(int index) {
        return children.get(index);
    }

    public void operation() {
        System.out.println("容器操作");
        for (Component component : children) {
            component.operation();
        }
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        Component leaf1 = new Leaf("A");
        Component leaf2 = new Leaf("B");

        Component composite = new Composite();
        composite.add(leaf1);
        composite.add(leaf2);

        Component leaf3 = new Leaf("C");
        Component leaf4 = new Leaf("D");

        Component composite2 = new Composite();
        composite2.add(leaf3);
        composite2.add(leaf4);

        composite.add(composite2);

        composite.operation();
    }
}

在这个示例中,我们使用组合模式来构造树形结构。我们首先定义了组件接口 Component,并创建了叶子节点类 Leaf 和容器节点类 Composite。在客户端代码中,我们创建了叶子节点和容器节点,并通过组合模式将它们组合在一起构成一个树形结构。然后我们调用容器节点的 operation 方法来对整个树形结构进行操作。通过组合模式,我们可以以统一的方式处理叶子节点和容器节点,并构建具有层次结构的组件树。

组合模式允许我们构建树形结构,并以统一的方式处理整体和部分的对象。通过这种方式,我们可以方便地对树形结构中的节点进行操作,而无需关心它们是叶子节点还是容器节点。

  • 25
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值