结构模式---桥接模式和装饰者模式

桥接模式

桥接模式适合解决两个维度的问题,可以使问题在两个维度上无限扩张,并且可以随意组合,比如下表:

发送消息的方式 紧急 一般
邮件 紧急消息邮件发送 一般消息邮件发送
短信 紧急消息短信发送 一般消息短信发送

类图特别像一个桥梁:
这里写图片描述
桥接模式必须由一方使用抽象类,持有使用接口的一方,建议描述动作的一方使用接口,描述形态的一方使用抽象类

消息类:

public abstract class AbstractMessage {
    private String message;
    private MessageSender sender;

    public AbstractMessage(String message, MessageSender sender) {
        this.message = message;
        this.sender = sender;
    }

    public void send() {
        sender.send(message);
    }
}
public class SpecialMessage extends AbstractMessage {
    public SpecialMessage(String message, MessageSender sender) {
        super("特别消息:" + message, sender);
    }
}
public class CommonMessage extends AbstractMessage {
    public CommonMessage(String message, MessageSender sender) {
        super("普通消息:" + message, sender);
    }
}

消息发送方式类:

public interface MessageSender {
    public void send(String message);
}
public class MailMessageSender implements MessageSender {
    @Override
    public void send(String message) {
        System.out.println("使用邮件发送消息:" + message);
    }
}
public class SMSMessageSender implements MessageSender {
    @Override
    public void send(String message) {
        System.out.println("使用短信发送消息:" + message);
    }
}

客户端类:

    public static void main(String[] args) {
        AbstractMessage message = new CommonMessage("message1", new MailMessageSender());
        message.send();
        message = new CommonMessage("message1", new SMSMessageSender());
        message.send();
        message = new SpecialMessage("message2", new MailMessageSender());
        message.send();
        message = new SpecialMessage("message2", new SMSMessageSender());
        message.send();
    }

输出:

使用邮件发送消息:普通消息:message1
使用短信发送消息:普通消息:message1
使用邮件发送消息:特别消息:message2
使用短信发送消息:特别消息:message2

装饰者模式

装饰者模式和桥接模式很像,也是解决两个维度问题,使两个维度可以自由扩展和组合
类图:
这里写图片描述
从外观上看装饰者模式和桥接模式的类图只有一个地方不一样,就是最上边的接口和抽象类间的关系,装饰者模式是实现接口,桥接是以组合的方式持有接口
被装饰类:

public interface Conponent {
    public int read();
}
public class ConcreteConponent1 implements Conponent {
    @Override
    public int read() {
        return 95;
    }
}
public class ConcreteConponent2 implements Conponent {
    @Override
    public int read() {
        return 96;
    }
}

装饰者:

public abstract class AbstractDecorator implements Conponent {
    protected Conponent conponent;

    public AbstractDecorator(Conponent conponent) {
        this.conponent = conponent;
    }
}
public class ConcreteDecorator1 extends AbstractDecorator {

    public ConcreteDecorator1(Conponent conponent) {
        super(conponent);
    }

    @Override
    public int read() {
        return conponent.read() - 1;
    }
}
public class ConcreteDecorator2 extends AbstractDecorator {

    public ConcreteDecorator2(Conponent conponent) {
        super(conponent);
    }

    @Override
    public int read() {
        return conponent.read() + 1;
    }
}

客户端:

public static void main(String[] args) {
        Conponent conponent1 = new ConcreteConponent1();
        Conponent decorator1 = new ConcreteDecorator1(conponent1);
        System.out.println("conponent1没有装饰前的值:" + conponent1.read() + ";被decorator1装饰后的值:" + decorator1.read());

        Conponent decorator2 = new ConcreteDecorator2(conponent1);
        System.out.println("conponent1没有装饰前的值:" + conponent1.read() + ";被decorator2装饰后的值:" + decorator2.read());
    }

输出:

conponent1没有装饰前的值:95;被decorator1装饰后的值:94
conponent1没有装饰前的值:95;被decorator2装饰后的值:96

个人觉得,选择装饰者模式还是桥接模式,只需要在定义抽象类的时候问一句,这个抽象类是不是就是这个接口呢,如果是,选择装饰着,如果不是则选择桥接,比如上边桥接的例子,邮件发送消息和短信发送消息相比于紧急消息和普通消息而言,它们其实不是消息而是一种发送方式;这里装饰者举的是java.io包的io流的例子,使用io的read方法,接口Conponent相当于抽象类InputStream,抽象类AbstractDecorator相当于FilterInputStream,这样一来,装饰出来的新流根本上讲还是个流,所以大家使用统一接口后者抽象类

模式 抽象类是否持有接口 抽象类和接口能否说成是一类东西
桥接 持有 不能
装饰者 不持有

猜你喜欢

转载自blog.csdn.net/weixin_43060721/article/details/82227318
今日推荐