装饰模式(Decorator)
简介通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。
模式定义
在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。
优缺点
优点
- 采用装饰模式扩展对象的功能比采用继承方式更加灵活
- 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合
缺点
- 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂
适用场景
- 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时
- 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时
模型结构
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象;
- 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责;
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能;
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任;
模型实现
package com.company.decorator;
public class DecoratorPattern {
public static void main(String[] args) {
Component zs = new Person("张三");
System.out.println("===================只装饰衣服===================");
Decorator clothesDecorator = new ClothesDecorator(zs);
clothesDecorator.show();
System.out.println("===================装饰衣服的基础上再装饰裤子===================");
Decorator trousersDecorator = new TrousersDecorator(clothesDecorator);
trousersDecorator.show();
}
}
//构件接口
interface Component {
void show();//构件方法
}
//具体构件角色==>人
class Person implements Component {
private final String name;
public Person(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println(this.name + " 的装饰");
}
}
//抽象装饰器
abstract class Decorator implements Component {
private final Component component;
//装饰器构造方法,传入构件角色
public Decorator(Component component) {
this.component = component;
}
public void show() {
if (this.component != null) {
this.component.show();
}
}
}
//具体装饰器===》衣服
class ClothesDecorator extends Decorator {
public ClothesDecorator(Component component) {
super(component);
}
public void show() {
super.show();
System.out.println("装饰===》衣服");
}
}
//具体装饰器===》裤子
class TrousersDecorator extends Decorator {
public TrousersDecorator(Component component) {
super(component);
}
public void show() {
super.show();
System.out.println("装饰===》裤子");
}
}
运行结果:
===================只装饰衣服===================
张三 的装饰
装饰===》衣服
===================装饰衣服的基础上再装饰裤子===================
张三 的装饰
装饰===》衣服
装饰===》裤子
缩放布局组件FittedBox主要有两个功能:缩放和位置调整。FittedBox会根据自己的尺寸来调整child的尺寸。
Tauri 是一个框架,用于为所有主要桌面平台构建小巧、快速的二进制文件。开发人员可以集成任何可编译为 HTML、JS 和 CSS 的前端框架,以构建他们的用户界面。应用程序的后端是一个基于 Rust 的二进制文件,带有一个前端可以与之交互的 API。
Tauri 应用程序的用户界面目前在 macOS 和 Windows 上利用 tao 作为窗口处理库,在 Linux 上通过 Tauri 团队孵化和维护的 WRY 利用 WebKit、Windows 上的 WebView2 和 Linux 上的 WebKitGTK 创建一个统一的系统 webview(和其他好东西,如菜单和任务栏)接口。
图像添加(高斯/椒盐/泊松/斑点)噪声
python多维数组为一维数组(reshape、flatten、ravel),使用NumPy库.
快速生成表格
Electron页面跳转、浏览器打开链接和打开新窗口
在使用Git的过程中,不想每次都输入用户名和密码去拉取代码,所以就需要保存这些信息,那么既然有保存了,就必须有清除功能。
Docker编译镜像出现:fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
ERROR: http://dl-cdn.alpinelinux.org/alpine/v3.12/main: temporary error (try again later)
WARNING: Ignoring APKINDEX.2c4ac24e.tar.gz: No such file or directory问题
在Mac电脑中,如何对Git的用户名和密码进行修改呢?起初不懂Mac,所以整了很久,本文将记录如何对这个进行操作,以便后期使用。