《图解设计模式》笔记(三)生成实例

news2024/12/26 21:25:21

五、Singleton模式:只有一个实例

Singleton 是指只含有一个元素的集合。因为本模式只能生成一个实例,因此以 Singleton命名。

示例程序类图

请添加图片描述

Singleton.java

public class Singleton {
    private static Singleton singleton = new Singleton();

    private Singleton() {
        System.out.println("生成了一个实例。");
    }

    public static Singleton getInstance() {
        return singleton;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("Start.");
        Singleton obj1 = Singleton.getInstance();
        Singleton obj2 = Singleton.getInstance();
        if (obj1 == obj2) {
            System.out.println("obj1与obj2是相同的实例。");
        } else {
            System.out.println("obj1与obj2是不同的实例。");
        }
        System.out.println("End.");
    }
}

运行结果

Start.
生成了一个实例。
obj1与obj2是相同的实例。
End.

扩展思路的要点

何时生成这个唯一的实例

注意示例程序的运行结果,在【Start.】之后就显示出了【生成了一个实例。】

程序运行后,在第一次调用 getInstance方法时,Singleton类会被初始化。也就是在这个时候,static字段singleton被初始化,生成了唯一的一个实例。

相关的设计模式

在以下模式中,多数情况下只会生成一个实例。

AbstractFactory 模式(第8章)

Builder 模式(第7章)

Facade 模式(第15章)

Prototype 模式(第6章)

六、Prototype模式:通过复制生成实例

Prototype模式:不根据类来生成实例(不使用 new ClassName() 的形式),而是根据实例来生成新实例

Prototype有“原型”“模型”的意思。在设计模式中,它是指根据实例原型、实例模型来生成新的实例。

Java可以使用clone创建出实例的副本。本章将学习clone方法与Cloneable接口的使用方法。

示例程序类图

在这里插入图片描述

Manager类

package framework;

import java.util.*;

public class Manager {
    private HashMap showcase = new HashMap();

    public void register(String name, Product proto) {
        showcase.put(name, proto);
    }

    public Product create(String protoname) {
        Product p = (Product) showcase.get(protoname);
        return p.createClone();
    }
}

Product接口

package framework;

import java.lang.Cloneable;

public interface Product extends Cloneable {
    public abstract void use(String s);

    public abstract Product createClone();
}

MessageBox类

import framework.*;

public class MessageBox implements Product {
    private char decochar;

    public MessageBox(char decochar) {
        this.decochar = decochar;
    }

    public void use(String s) {
        // 业务逻辑:把传入的s用decochar包围打印
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

UnderlinePen类

与MessageBox几乎相同,use()方法中对s进行加下划线打印

import framework.*;

public class UnderlinePen implements Product {
    private char ulchar;

    public UnderlinePen(char ulchar) {
        this.ulchar = ulchar;
    }

    public void use(String s) {
        // 业务逻辑:把传入的s用decochar加下划线打印
    }

    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

Main测试类

import framework.*;

public class Main {
    public static void main(String[] args) {
        // 准备
        Manager manager = new Manager();
        UnderlinePen upen = new UnderlinePen('~');
        MessageBox mbox = new MessageBox('*');
        MessageBox sbox = new MessageBox('/');
        manager.register("strong message", upen);
        manager.register("warning box", mbox);
        manager.register("slash box", sbox);

        // 生成
        Product p1 = manager.create("strong message");
        p1.use("Hello, world.");
        Product p2 = manager.create("warning box");
        p2.use("Hello, world.");
        Product p3 = manager.create("slash box");
        p3.use("Hello, world.");
    }
}

运行结果

在这里插入图片描述

角色

在这里插入图片描述

  • Prototype(原型)

    负责定义用于复制现有实例来生成新实例的方法。在示例程序中,由Product接口扮演此角色。

  • ConcretePrototype(具体的原型)

    负责实现复制现有实例并生成新实例的方法。在示例程序中,由MessageBox类和UnderlinePen类扮演此角色。

  • Client(使用者)

    负责使用复制实例的方法生成新的实例。在示例程序中,由Manager类扮演此角色。

扩展思路的要点

不能根据类来生成实例吗

根据类生成实例:new Something()

不根据类生成实例的场景:

  1. 对象种类繁多,无法将它们整合到一个类中时

示例程序中,一共出现了3种对字符串处理的样式。但只要想做,能支持更多样式。

但若将每种样式都编写为一个类,类的数量将太多,较难管理源程序。

  1. 难以根据类生成实例时

本例中感觉不到这一点。试想若要开发一个用户可以使用鼠标进行操作的、类似于图形编辑器的应用程序,可能更容易理解。

假设我们想生成一个和用户通过一系列鼠标操作所创建出来的实例完全一样的实例,此时,与根据类来生成实例相比,根据实例来生成实例要更简单。

  1. 想解耦框架与生成的实例时

在示例程序中,我们将复制(clone)实例的部分封装在 framework包中了。

在Manager类的create方法中,没使用类名,取而代之使用了strong messageslash box等字符串为生成的实例命名。

与Java自带的生成实例的new Something()方式相比,这种方式具有更好的通用性,而且将框架从类名的束缚中解脱出来了。

类名是束缚吗

在源程序中使用类名到底会有什么问题?在代码中出现要使用的类的名字不是理所当然的吗?

再回忆一下面向对象编程的目标之一:作为组件复用

一旦在代码中出现要使用的类的名字,就无法与该类分离开来,也就无法实现复用。

虽然可以通过替换源代码或改变类名来解决这个问题。但此处说的“作为组件复用”不包含替换源代码。

以Java来说,重要的是当手边只有class文件(.class)时,该类能否被复用。即使没有Java文件(.java)也能复用该类才是关键。

当多个类必须紧密结合时,代码中出现这些类的名字没问题。但若那些需要被独立出来作为组件复用的类的名字出现在代码中,那就有问题了。

相关的设计模式

Flyweight 模式(第20章)

Prototype 模式可以生成一个与当前实例的状态完全相同的实例。

Flyweight 模式可以在不同的地方使用同一个实例。

Memento 模式(第18章)

Prototype 模式可以生成一个与当前实例的状态完全相同的实例。

Memento 模式可以保存当前实例的状态,以实现快照和撤销功能。

Composite 模式(第11章)以及Decorator模式(第12章)

经常使用Composite模式和Decorator模式时,需要能够动态地创建复杂结构的实例。这时可以使用 Prototype模式,以帮助我们方便地生成实例。

Command 模式(第22章)

想要复制Command 模式中出现的命令时,可以使用 Prototype模式。

补充:Clone注意事项

clone方法所进行的复制只是将被复制实例的字段值直接复制到新的实例中,即它没考虑字段中所保存的实例的内容。

例如,当字段中保存的是数组时,如果使用clone方法进行复制,则只会复制该数组的引用,并不会一一复制数组中的元素。

像上面这样的字段对字段的复制(field-to-field-copy)被称为浅复制(shallow copy)。clone方法所进行的复制就是浅复制。

当使用clone方法进行浅复制无法满足需求时,可以重写 clone方法,实现自己需要的复制功能(重写clone方法时,别忘了使用super.clone()来调用父类的clone方法)。

clone方法只进行复制,不会调用被复制实例的构造函数。

对于在生成实例时需要进行特殊的初始化处理的类,需要自己去实现clone方法,在其内部进行这些初始化处理。

七、Builder模式:组装复杂的实例

示例程序类图

在这里插入图片描述

注意:此案例中Builder是抽象类,但也可以用interface来实现这个模式。

Director类

public class Director {
    private Builder builder;

    public Director(Builder builder) {
        // 接收的参数是Builder类的子类,所以可以将其保存在builder字段中
        this.builder = builder;
    }

    // 编写文档
    public void construct() {
        // 标题、字符串、条目
        builder.makeTitle("Greeting");
        builder.makeString("从早上至下午");
        builder.makeItems(new String[]{"早上好。", "下午好。"});
        // 其他字符串、其他条目
        builder.makeString("晚上");
        builder.makeItems(new String[]{"晚上好。", "晚安。", "再见。"});
        // 完成文档
        builder.close();
    }
}

TextBuilder类

public class TextBuilder extends Builder {
    // 文档内容保存在该字段中
    private StringBuffer buffer = new StringBuffer();

    // 纯文本的标题
    public void makeTitle(String title) {
        // 业务逻辑:buffer.append 装饰线、为标题添加『』、换行
    }

    // 纯文本的字符串
    public void makeString(String str) {
        // 业务逻辑:buffer.append 为字符串添加■、换行
    }

    // 纯文本的条目
    public void makeItems(String[] items) {
        // 业务逻辑:buffer.append 为条目添加・、换行
    }

    // 完成文档 添加装饰线
    public void close() {
        buffer.append("==============================\n");
    }

    // 完成的文档
    public String getResult() {                                 
        return buffer.toString();
    }
}

HTMLBuilder类

import java.io.*;

public class HTMLBuilder extends Builder {
    private String filename;                                                        // 文件名
    private PrintWriter writer;                                                     // 用于编写文件的PrintWriter
    public void makeTitle(String title) {                                           // HTML文件的标题
        filename = title + ".html";                                                 // 将标题作为文件名
        try {
            writer = new PrintWriter(new FileWriter(filename));                     // 生成 PrintWriter
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.println("<html><head><title>" + title + "</title></head><body>");    // 输出标题
        writer.println("<h1>" + title + "</h1>");
    }
    public void makeString(String str) {                                            // HTML文件中的字符串
        writer.println("<p>" + str + "</p>");                                       // 用<p>标签输出
    }
    public void makeItems(String[] items) {                                         // HTML文件中的条目
        writer.println("<ul>");                                                     // 用<ul>和<li>输出
        for (int i = 0; i < items.length; i++) {
            writer.println("<li>" + items[i] + "</li>");
        }
        writer.println("</ul>");
    }
    public void close() {                                                           // 完成文档
        writer.println("</body></html>");                                           // 关闭标签
        writer.close();                                                             // 关闭文件
    }
    public String getResult() {                                                     // 编写完成的文档
        return filename;                                                            // 返回文件名
    }
}

Main测试类

public class Main {
    public static void main(String[] args) {
        if (args.length != 1) {
            usage();
            System.exit(0);
        }
        if (args[0].equals("plain")) {
            TextBuilder textbuilder = new TextBuilder();
            Director director = new Director(textbuilder);
            director.construct();
            String result = textbuilder.getResult();
            System.out.println(result);
        } else if (args[0].equals("html")) {
            HTMLBuilder htmlbuilder = new HTMLBuilder();
            Director director = new Director(htmlbuilder);
            director.construct();
            String filename = htmlbuilder.getResult();
            System.out.println(filename + "文件编写完成。");
        } else {
            usage();
            System.exit(0);
        }
    }

    public static void usage() {
        System.out.println("Usage: java Main plain      编写纯文本文档");
        System.out.println("Usage: java Main html       编写HTML文档");
    }
}

角色

在这里插入图片描述

  • Builder(建造者)

    负责定义用于生成实例的接口(API)。Builder角色中准备了用于生成实例的方法。在示例程序中,由Builder类扮演此角色。

  • ConcreteBuilder(具体的建造者)

    是负责实现 Builder角色的接口的类(API),定义了在生成实例时实际被调用的方法、获取最终生成结果的方法。

    在示例程序中,由TextBuilder类和HTMLBuilder类扮演此角色。

  • Director(监工)

    负责使用Builder角色的接口(API)来生成实例。它并不依赖于ConcreteBuilder角色。

    为了确保不论ConcreteBuilder角色是如何被定义的,Director角色都能正常工作,它只调用在Builder角色中被定义的方法。

    在示例程序中,由Director类扮演此角色。

  • Client(使用者)

    该角色使用了Builder模式(Builder模式并不包含Client角色)。

    在示例程序中,由Main类扮演此角色。

相关的设计模式

Template Method模式(第3章)

Builder模式:Director角色控制Builder角色。

Template Method模式:父类控制子类。

Composite 模式(第11章)

有些情况下 Builder模式生成的实例构成了Composite模式。

Abstract Factory模式(第8章)

Builder模式和Abstract Factory模式都用于生成复杂的实例。

Facade模式(第15章)

在 Builder模式中,Director角色通过组合 Builder角色中的复杂方法向外部提供可以简单生成实例的接口(API)(相当于示例程序中的construct方法)。

Facade模式中的 Facade角色则是通过组合内部模块向外部提供可以简单调用的接口(API)。

扩展思路的要点

谁知道什么

Director类不知道自己使用的究竟是Builder类的哪个子类也好。因为“只有不知道子类才能替换”。

正是因为可以替换,组件才具有高价值。作为设计人员,我们必须时刻关注这种“可替换性”。

设计时能够决定的事情和不能决定的事情

在Builder类中,需要声明编辑文档(实现功能)所必需的所有方法,在Builder类中应当定义哪些方法很重要。

而且,Builder类还必须能够应对将来子类可能增加的需求,若将来要新编写一种文档类型的子类实现,是否需要新的方法?

虽然类的设计者无法准确地预测到将来可能发生的变化,但还是有必要让设计出的类能够尽可能灵活地应对近期可能发生的变化。

代码的阅读方法和修改方法

如果没有理解各个类的角色就动手增加和修改代码,在判断到底应该修改哪个类时,就会很容易出错。

八、Abstract Factory模式:将关联零件组装成产品

在 Abstract Factory模式中,不仅有“抽象工厂”,还有“抽象零件”和“抽象产品”。抽象工厂的工作是将“抽象零件”组装为“抽象产品”。

回顾面向对象编程中的“抽象”这个词的具体含义:它指的是“不考虑具体怎样实现,而是仅关注接口(API)"的状态。

例如,抽象方法(Abstract Method)并不定义方法的具体实现,而是仅仅只确定了方法的名字和签名(参数的类型和个数)。

我们不关心零件的具体实现,而只关心接口(API),仅使用该接口(API)将零件组装成为产品。

在 Tempate Method模式和Builder模式中,子类这一层负责方法的具体实现。

在 AbstractFactory模式中也是一样的。在子类这一层中有具体的工厂,它负责将具体的零件组装成为具体的产品。

本章中的示例程序的功能是将带有层次关系的链接的集合制作成HTML文件。

示例程序类图

在这里插入图片描述

factory包 - 抽象

Item
package factory;

public abstract class Item {
    protected String caption;
    public Item(String caption) {
        this.caption = caption;
    }
    public abstract String makeHTML();
}
Link
package factory;

public abstract class Link extends Item {
    protected String url;
    public Link(String caption, String url) {
        super(caption);
        this.url = url;
    }
}
Tray
package factory;

import java.util.ArrayList;

public abstract class Tray extends Item {
    protected ArrayList tray = new ArrayList();

    public Tray(String caption) {
        super(caption);
    }

    // 将Link类和Tray类集合在一起。为表示集合的对象是“Link类和Tray类”,我们设置add方法的参数为Link类和Tray类的父类Item类。
    public void add(Item item) {
        tray.add(item);
    }
}
Page
package factory;

import java.io.*;
import java.util.ArrayList;

public abstract class Page {
    protected String title;
    protected String author;
    protected ArrayList content = new ArrayList();

    public Page(String title, String author) {
        this.title = title;
        this.author = author;
    }

    // 向页面中增加Item(即Link或Tray)。增加的Item将会在页面中显示出来。
    public void add(Item item) {
        content.add(item);
    }

    // output方法是一个简单的 Template Method模式 的方法。
    public void output() {
        try {
            // 首先 根据页面标题确定文件名
            String filename = title + ".html";
            Writer writer = new FileWriter(filename);
            // 然后 调用makeHTML抽象方法将自身保存的HTML内容写入到文件中。
            writer.write(this.makeHTML());
            writer.close();
            System.out.println(filename + " 编写完成。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public abstract String makeHTML();
}
Factory
package factory;

public abstract class Factory {

    // 虽然getFactory方法生成的是具体工厂的实例,但是返回值的类型是抽象工厂类型
    public static Factory getFactory(String classname) {
        Factory factory = null;
        try {
            // 根据 类名字符串 生成具体工厂的实例。
            factory = (Factory) Class.forName(classname).newInstance();
        } catch (ClassNotFoundException e) {
            System.err.println("没有找到 " + classname + "类。");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return factory;
    }

    // createLink、createTray、createPage等方法 是用于在抽象工厂中生成零件和产品的方法
    public abstract Link createLink(String caption, String url);

    public abstract Tray createTray(String caption);

    public abstract Page createPage(String title, String author);
}

listfactory - 具体

ListFactory
package listfactory;
import factory.*;

public class ListFactory extends Factory {
    // 各个方法内部只是分别简单地new出了对应类的实例(根据实际需求,这里可能需要用 Prototype模式来进行clone)
    public Link createLink(String caption, String url) {
        return new ListLink(caption, url);
    }
    public Tray createTray(String caption) {
        return new ListTray(caption);
    }
    public Page createPage(String title, String author) {
        return new ListPage(title, author);
    }
}
ListLink
package listfactory;
import factory.*;

public class ListLink extends Link {
    public ListLink(String caption, String url) {
        super(caption, url);
    }
    public String makeHTML() {
        return "  <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
    }
}
ListTray
package listfactory;

import factory.*;

import java.util.Iterator;

public class ListTray extends Tray {
    public ListTray(String caption) {
        super(caption);
    }

    public String makeHTML() {
        StringBuffer buffer = new StringBuffer()
                .append("<li>\n")
                .append(caption + "\n")
                .append("<ul>\n");
        Iterator it = tray.iterator();
        while (it.hasNext()) {
            Item item = (Item) it.next();
            // 这里并不关心变量item中保存的实例究竟是ListLink的实例还是ListTray的实例,只是简单地调用了item.makeHTML()语句而已。
            // 同时这里不能使用 switch语句或if语句去判断变量item中保存的实例的类型,否则就不是面向对象编程了。
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n")
                .append("</li>\n");
        return buffer.toString();
    }
}
ListPage
package listfactory;

import factory.*;

import java.util.Iterator;

public class ListPage extends Page {
    public ListPage(String title, String author) {
        super(title, author);
    }

    public String makeHTML() {
        StringBuffer buffer = new StringBuffer()
                .append("<html><head><title>" + title + "</title></head>\n")
                .append("<body>\n")
                .append("<h1>" + title + "</h1>\n")
                .append("<ul>\n");
        // content继承自Page类的字段。
        Iterator it = content.iterator();
        while (it.hasNext()) {
            Item item = (Item) it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n")
                .append("<hr><address>" + author + "</address>")
                .append("</body></html>\n");
        return buffer.toString();
    }
}

Main

import factory.*;

public class Main {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: java Main class.name.of.ConcreteFactory");
            System.out.println("Example 1: java Main listfactory.ListFactory");
            System.out.println("Example 2: java Main tablefactory.TableFactory");
            System.exit(0);
        }
        Factory factory = Factory.getFactory(args[0]);

        Link people = factory.createLink("人民日报", "http://www.people.com.cn/");
        Link gmw = factory.createLink("光明日报", "http://www.gmw.cn/");

        Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
        Link jp_yahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp/");
        Link excite = factory.createLink("Excite", "http://www.excite.com/");
        Link google = factory.createLink("Google", "http://www.google.com/");

        Tray traynews = factory.createTray("日报");
        traynews.add(people);
        traynews.add(gmw);

        Tray trayyahoo = factory.createTray("Yahoo!");
        trayyahoo.add(us_yahoo);
        trayyahoo.add(jp_yahoo);

        Tray traysearch = factory.createTray("检索引擎");
        traysearch.add(trayyahoo);
        traysearch.add(excite);
        traysearch.add(google);

        Page page = factory.createPage("LinkPage", "杨文轩");
        page.add(traynews);
        page.add(traysearch);
        page.output();
    }
}

为示例程序增加其他工厂

当只有一个具体工厂的时候,没有必要划分“抽象类”与“具体类”。

可以为示例程序增加其他的具体工厂,比如编写含有表格的HTML格式的文件。

之前的listfactory包的功能是将超链接以条目形式展示出来,

现在可以新建tablefactory包,在其下编写其他工厂将链接以表格形式展示出来:

新增TableFactory、TableLink、TableTray、TablePage,内容与listfactory包下对应的类相似,只是在编写html具体内容时有些要改为table标签之类的。

角色

在这里插入图片描述

  • AbstractProduct(抽象产品)

    定义 AbstractFactory 角色所生成的抽象零件和产品的接口(API)。

    示例中是 Link类、Tray类、Page类

  • AbstractFactory(抽象工厂)

    定义用于生成抽象产品的接口(API)。

    示例中是 Factory类

  • Client(委托者)

    仅会调用 AbstractFactory角色和AbstractProduct 角色的接口(API)来进行工作,不知道具体的零件、产品、工厂。

    示例中是 Main类,上图省略了这一角色。

  • ConcreteProduct(具体产品)

    实现AbstractProduct 角色的接口(API)。

    示例中是以下

    listfactory包:ListLink类、ListTray类、ListPage类

    tablefactory包:TableLink类、TableTray类、TablePage类

  • ConcreteFactory(具体工厂)

    实现AbstractFactory角色的接口(API)。

    示例中是以下

    listfactory包:Listfactory类

    tablefactory包:Tablefactory类

拓展思路的要点

易于增加具体的工厂

在本模式中很容易增加具体的工厂,因为需要编写哪些类和需要实现哪些方法都非常清楚。

无论要增加多少个具体工厂(或是要修改具体工厂的 Bug),都无需修改抽象工厂和 Main部分。

难以增加新的零件

怎么在 Abstract Factory模式中增加新的零件?

例如,我们要在factory包中增加一个表示图像的Picture零件,必须对所有的具体工厂进行相应的修改才行。

具体来说,在listfactory包中,需做修改:在ListFactory 中加入createPicture方法,新增ListPicture类。

已编写完成的具体工厂越多,修改的工作量就会越大。

相关的设计模式

Builder 模式(第7章)

Abstract Factory 模式:通过调用抽象产品的接口(API)来组装抽象产品,生成具有复杂结构的实例。

Builder 模式:分阶段地制作复杂实例。

Factory Method模式(第4章)

有时Abstract Factory 模式中零件和产品的生成会使用到 Factory Method模式。

Composite模式(第11章)

有时Abstract Factory模式在制作产品时会使用Composite模式。

Singleton 模式(第5章)

有时Abstract Factory 模式中的具体工厂会使用 Singleton模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2055903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

达林顿管阵列ULN2003的用途就是非门(输入和输出的关系)

对于UL2003来说&#xff0c;可以看作是非门。 输入为1&#xff0c;输出为0&#xff1b; 输入为0&#xff0c;输出为高组态[接一个上拉电阻即为1] 下面的可以不用看了&#xff0c;如果你想了解深入一点&#xff0c;可以往下看看。 ULN2003A就是个达林顿管&#xff0c; 一&am…

C++入门——“继承”

一、引入 面相对象的计算机语言有三大特性&#xff1a;“封装”、“继承”、“多态”。今天来讲解一下C的一大重要特性——继承。 通俗理解来讲&#xff0c;继承就和现实生活一样&#xff0c;子辈继承父辈的一些特性&#xff0c;C中的继承也可以这样理解。它允许我们在保持原有…

Windows C++控制台菜单库开发与源码展示

Windows C控制台菜单库 声明&#xff1a;演示视频&#xff1a;一、前言二、具体框架三、源码展示console_screen_set.hframeconsole_screen_frame_base.hconsole_screen_frame_char.hconsole_screen_frame_wchar_t.hconsole_screen_frame.h menuconsole_screen_menu_base.hcons…

html+css 实现hover 凹陷按钮

前言:哈喽,大家好,今天给大家分享html+css 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、原理解析💡1.这是一个,hover时凹陷的效果。每个按钮是一个button…

【Android 远程数据库操作】

按正常情况下&#xff0c;前端不应该直接进行远程数据库操作&#xff0c;这不是一个明智的方式&#xff0c;应该是后端提供对应接口来处理&#xff0c;奈何公司各方面原因需要前端这样做。 对此&#xff0c;我对远程数据库操作做了总结&#xff0c;便于自己复盘&#xff0c;同…

机器学习第十四章-概率图模型

目录 14.1 隐马尔可夫模型 14.2马尔科夫随机场 14.3条件随机场 14.4学习与推断 14.4.1变量消去 14.4.2信念传播 14.5近似推断 14.5.1 MCMC采样 14.5.2 变分推断 14.6 话题模型 14.1 隐马尔可夫模型 概率围棋型是一类用图来表达变量相关关系的概率模型.它以图为表示工具…

Transformer(课程笔记)

一&#xff1a;Motivation RNN需要顺序的执行&#xff0c;不利于并行计算。 RNN的变体例如GRU、LSTM等需要依靠注意力机制解决信息瓶颈等问题。 抛弃RNN结构&#xff0c;提出了Transformer结构。 Transformer整体架构 二&#xff1a; 输入层&#xff08;BPE&#xff0c;PE&…

《黑神话:悟空》玩家必看!AMD显卡驱动24.8.1版全力支持!

系统之家于8月20日发出最新报道&#xff0c;AMD发布了最新的24.8.1版本驱动&#xff0c;本次更新增加了《黑神话&#xff1a;悟空》《星球大战&#xff1a;亡命之徒》等游戏的支持&#xff0c;且HYPR Tune支持允许HYPR-RX启用游戏内技术。下面跟随小编一起来看看AMD显卡驱动24.…

Centos7 message日志因dockerd、kubelet、warpdrive、containerd等应用迅速增长

问题&#xff1a;公司服务器在部署一套业务后&#xff0c;message日志记录大量的dockerd、kubelet、warpdrive、containerd应用日志&#xff0c;每天增加2G大小的日志 解决方案&#xff1a; 前期吐槽下&#xff1a;发现某个帖子&#xff0c;需要会员或者花钱才能看&#xff0c…

探索网络安全的深度与广度:挑战、策略与未来展望

一、引言 在当今数字化的时代&#xff0c;网络已经成为社会运转的核心基础设施之一。从个人的日常通信、娱乐到企业的业务运营、国家的关键服务&#xff0c;几乎所有领域都依赖于网络。然而&#xff0c;随着网络的普及和应用的深化&#xff0c;网络安全问题也日益凸显&#xf…

松下弧焊机器人维修 控制柜故障 连接线修复

一、Panasonic焊接机器人控制柜与机器人的接线 机器人的控制箱&#xff0c;一定要配对使用。松下焊接机器人控制柜已经记忆了机器人的绝对原点(机器人位置控制原点)。 二、编码器电缆 (圆形连接器) 1. 接口的插头插座要注意&#xff0c;插头要插到插座中。 2. 用一手握住电缆&a…

网络原理TCP/UDP详解

目录 传输属的几种格式 1.xml&#xff1a;通过成对的标签表示键值对信息。 2.json&#xff1a;当前更主流一点的&#xff0c;网络通信的数据格式 3.yml&#xff08;yaml&#xff09;强制要求数据的组织格式 4.google protobuffer 传输层 1.端口号&#xff1a; UDP协议 …

Vue3 组件管理 12 种神仙写法,灵活使用才能提高效率

SFC 单文件组件 顾名思义&#xff0c;就是一个.vue文件只写一个组件 模板写法 如果这个组件想要在别的组件里使用&#xff0c;就需要在另一个.vue中引入和使用、复用 h函数写法 使用 defineComponent h 去进行组件编写 JSX/TSX写法 使用 defineComponent JSX/TSX 去进行…

【html+css 绚丽Loading】 - 000008 三才虚空灵瞳

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…

应用方案 | 降压型DC-DC电源管理电路 D2576介绍

概述 D2576是一款高效降压型DC-DC转换器&#xff0c;固定52KHz开关频率&#xff0c;可以提供最高3A输出电流能力&#xff0c;具有低纹波&#xff0c;出色的线性调整率与负载调整率特点。 D2576内置固定频率振荡器与频率补偿电路&#xff0c;简化了电路设计。PWM控制环路可以调节…

Rivian暂停亚马逊送货车生产,特斯拉Roadster再引关注

Rivian遭遇供应链挑战&#xff0c;暂停亚马逊送货车生产 电动汽车制造商Rivian近期宣布&#xff0c;由于零部件短缺&#xff0c;已暂停为零售巨头亚马逊生产商业送货车。这一决定标志着Rivian在应对供应链挑战方面遭遇了最新挫折。作为Rivian的最大投资者&#xff0c;亚马逊持有…

画板444

p31 画H1和H2的封装 立创里面这次有尺寸了没单位好像 给的1.02 他设的1.1焊盘可以大点 排针穿过去的&#xff08;别的焊盘也这样&#xff1f;&#xff09; 引脚编号 直接改成2.54 他焊盘直间的 距离了 刚才改成通用的直径了&#x1f605;&#x1f605;&#x1f605; 这能测尺寸…

金九银十,软件测试面试八股文【含答案+文档】

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件…

google seo基础宝典,新手必学

Google SEO 是什么&#xff1f; Google SEO是指针对谷歌搜索引擎优化网站排名的一种营销方式&#xff0c;旨在提升外贸网站在谷歌的品牌和产品曝光度&#xff0c;从而吸引外贸订单。具体做法是根据谷歌的搜索引擎排名规则&#xff0c;对网站的内容、结构、链接等方面进行优化&a…

C++竞赛初阶L1-13-第五单元-循环嵌套(29~30课)536: T456455 画矩形

题目内容 根据输入的四个参数&#xff1a;a,b,c,f 参数&#xff0c;画出对应的矩形。 前两个参数 a,b 为整数&#xff0c;依次代表矩形的高和宽&#xff1b; 第三个参数 c 是一个字符&#xff0c;表示用来填充的矩形符号&#xff1b; 第四个参数 f 为整数&#xff0c;0 代表…