其他分享
首页 > 其他分享> > 设计模式 桥接模式 其在JDK中的应用

设计模式 桥接模式 其在JDK中的应用

作者:互联网

桥接模式

定义

桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and
Body)模式或接口(Interfce)模式。

使用场景

桥我们大家都熟悉,顾名思义就是用来将河的两岸联系起来的。而此处的桥是用来将两个独立的结构联系起来,而这两个被联系起来的结构可以独立的变化,所有其他的理解只要建立在这个层面上就会比较容易。

下面是一些官方的说明,

优点:

缺点:

uml图

在这里插入图片描述

桥梁模式所涉及的角色有:

场景

星巴克的咖啡有大杯中杯超大杯,口味有原味加奶加糖

分析当前业务场景,认为可以将咖啡的容量作为抽象化Abstraction,而咖啡口味为实现化Implementor

第一步:创建实现化部分的接口定义(咖啡口味的维度)

public interface ICoffeeAdditives {
    void addSomething();
}

第二步:创建抽象化部分的接口定义(咖啡容量的维度)

//抽象化Abstraction
public abstract class Coffee {
    protected ICoffeeAdditives additives;
    public Coffee(ICoffeeAdditives additives){
        this.additives=additives;
    }
    public abstract void orderCoffee(int count);
}

第三步:实现实现化部分(咖啡口味维度)的接口ICoffeeAdditives

//加奶
public class Milk implements ICoffeeAdditives {
    @Override
    public void addSomething() {
        System.out.println("加奶");
    }
}
//加糖
public class Sugar implements ICoffeeAdditives {
    @Override
    public void addSomething() {
        System.out.println("加糖");
    }

第四步:实现抽象化部分(咖啡的容量维度)的接口Coffee

public class LargeCoffee extends Coffee {
    public LargeCoffee(ICoffeeAdditives additives) {
        super(additives);
    }
    @Override
    public void orderCoffee(int count) {
        additives.addSomething();
        System.out.println(String.format("大杯咖啡%d杯",count));
    }
}
//小杯
public class SmallCoffee extends Coffee {
    public SmallCoffee(ICoffeeAdditives additives) {
        super(additives);
    }

    @Override
    public void orderCoffee(int count) {
        additives.addSomething();
        System.out.println(String.format("小杯咖啡%d杯",count));
    }
}

第五步:客户端调用

public class test {
    public static void main(String[] args) {
        //点两杯加奶的大杯咖啡
        Coffee largeWithMilk=new LargeCoffee(new Milk());
        largeWithMilk.orderCoffee(2);
        SmallCoffee smallCoffee = new SmallCoffee(new Sugar());
        smallCoffee.orderCoffee(1);
    }
}

结果

在这里插入图片描述

通过使用桥接模式,就使得咖啡的容量和口味这两个维度可以独立变化,互不干扰。原本需要2x2=4个类的功能,现在只需要2+2=4 个类,有的同学就要说了,我去,加上那些基类和原来也差不多,没有多好啊?别急,等来了新需求你就知道哪个好了。新需求:增加一种加蜂蜜的口味,现在不使用桥接模式的类的个数是2x3=6,而使用了的是2+3=5,你说哪个好。

jdk 源码的桥接模式

java.util.logging是JDK自带的日志包,可以将日志输出到文件、内存或者控制台,作用与我们常用的log4j类似。
包中的Handler类和Formatter类在设计上利用了桥接模式,首先看类关系图:

在这里插入图片描述
Handle和Formatter类是两个抽象类,它们可以分别独立的变化(有不同的子类);而Handle类中包含对Formatter类的引用。

public abstract class Handler {
    private static final int offValue = Level.OFF.intValue();
    private final LogManager manager = LogManager.getLogManager();
    private volatile Filter filter;
    //引用 Formatter
    private volatile Formatter formatter;
    
    private volatile Level logLevel = Level.ALL;
    private volatile ErrorManager errorManager = new ErrorManager();
    private volatile String encoding;
    //设置Formatter
    public synchronized void setFormatter(Formatter newFormatter) throws SecurityException {
        checkPermission();
        // Check for a null pointer:
        newFormatter.getClass();
        formatter = newFormatter;
    }

Handle通过setFormatter方法可以方便的替换不同的Formatter类。

Handle与Formatter介绍

1、Handlej和实现类

在这里插入图片描述
handle对象可以从一个logger中取出信息并输出到控制台、文件或者调用其它api发送到网络中;
handle可以通过setLevel方法关闭或打开;
handle通常是利用LogManager去设置自身的Handler、Filter、Formatter等属性值。
*备注:虽然父类Handle中提供了setFormatter方法,但子类streamhandle中也重新提供了配置各个成员变量值的方法:

private void configure() {
        LogManager manager = LogManager.getLogManager();
        String cname = getClass().getName();
        setLevel(manager.getLevelProperty(cname +".level", Level.INFO));
        setFilter(manager.getFilterProperty(cname +".filter", null));
        setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
        try {
            setEncoding(manager.getStringProperty(cname +".encoding", null));
        } catch (Exception ex) {
            try {
                setEncoding(null);
            } catch (Exception ex2) {
                // doing a setEncoding with null should always work.
                // assert false;
            }
        }
    }

2、Formatter和实现类

在这里插入图片描述
Formatter支持格式化日志数据;通常每个Handler中都会有一个Formatter引用,Formatter可以将LogRecord对象转换为一个string字符串。

SimpleFormatter 的方法
 public synchronized String format(LogRecord record) {
        dat.setTime(record.getMillis());
        String source;
        if (record.getSourceClassName() != null) {
            source = record.getSourceClassName();
            if (record.getSourceMethodName() != null) {
               source += " " + record.getSourceMethodName();
            }
        } else {
            source = record.getLoggerName();
        }
        String message = formatMessage(record);
        String throwable = "";
        if (record.getThrown() != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            pw.println();
            record.getThrown().printStackTrace(pw);
            pw.close();
            throwable = sw.toString();
        }
        return String.format(format,
                             dat,
                             source,
                             record.getLoggerName(),
                             record.getLevel().getLocalizedLevelName(),
                             message,
                             throwable);
    }


标签:Formatter,JDK,桥接,record,抽象化,维度,设计模式,public
来源: https://blog.csdn.net/A980719/article/details/120769572