适配器模式与桥接模式

适配器模式

适配器模式(Adapter Pattern),它的目的是将一个类的接口编程客户端所期望的另一种接口,从而是原本接口不匹配而导致无法在一起工作的两个类能一起工作,属于结构型设计模式。

适配器模式的角色:

目标角色(Target):也就是我们期望的接口

源角色(Adaptee):存在系统中,内容满足客户需求(需转换),但是接口不匹配的接口实例

适配器(Adapter): 将源角色(Adaptee)转换成目标角色(Target)的类实例

适配器模式有3中方式: 类适配器 对象适配器 接口适配器

//类适配器,适配器直接继承源角色,实现目标角色实现转换
public interface DC5output {
    public int output();
}

public class DC220output {
    public int output220(){
        System.out.println("调用输出220v");
        return 220;
    }
}

public class PowerAdapter extends DC220output implements DC5output{
    public int output() {
        System.out.println("将220v转换为5v");
        int i = super.output220();
        int target = i/44;
        System.out.println("输入电压:" + i +"v,输出电压:" + target + "v");
        return target;
    }

    public static void main(String[] args) {
        PowerAdapter powerAdapter = new PowerAdapter();
        powerAdapter.output();
    }
}
//对象适配器,实现目标适配器 并持有源目标的对象引用
public interface DC5output {
    public int output();
}

public class DC220output {
    public int output220(){
        System.out.println("调用输出220v");
        return 220;
    }
}

public class PowerAdapter implements DC5output{
    private DC220output dc220output;

    public PowerAdapter(DC220output dc220output) {
        this.dc220output = dc220output;
    }

    public int output() {
        int i = dc220output.output220();
        int target = i/44;
        System.out.println("输入电压:" + i + "v,输出电压:" + target + "v");
        return target;
    }

    public static void main(String[] args) {
        DC220output dc220output = new DC220output();
        PowerAdapter powerAdapter = new PowerAdapter(dc220output);
        powerAdapter.output();
    }
}

//接口适配主要是为了解决目标接口过多,直接实现需要实现大量空方法,通过中间适配对象去实现目标接口,减少空实现

public interface DC {
    int output5V();
    int output12V();
    int output24V();
    int output36V();
}
public class AC220 {
    public int output220V(){
        int output = 220;
        System.out.println("输出电压:" + output + "V");
        return output;
    }
}
public class PowerAdapter implements DC{
    private AC220 ac220;

    public PowerAdapter(AC220 ac220) {
        this.ac220 = ac220;
    }

    public int output5V() {
        int adapterInput = ac220.output220V();
        int adapterOutput = adapterInput/44;
        System.out.println("输入电压:" + adapterInput + "V,输出电压:" + adapterOutput + "V");
        return adapterOutput;
    }

    /**
     * 提供默认实现
     * @return
     */
    public int output12V() {
        return 0;
    }

    public int output24V() {
        return 0;
    }

    public int output36V() {
        return 0;
    }
}

源码中适配器模式的使用

源码中还有适配器的一种特殊实现,看起来更像是一种策略模式,但是他注重的为了匹配现有的功能,而策略模式是注重的是根据传入条件选择一种方式实现目标。所以说设计模式不是单独存在的,要灵活对待。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
       ...

        try {
            try {
                ...

                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
					//传入的mappedHandler.getHandler()类型丢失了是一个Object类型
                    //系统只知道它是几种类型之一,如果直接用instance判断,代码耦合严重
                    //因此为可能出现的所有类型提供一个适配器,并缓存到集合中,迭代通过适配器的support方法去判断是否匹配,然后通过适配器的handler方法,调用原有mappedHandler.getHandler()原始对象的handler方法
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

					...
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                   ...
    }
                
public interface HandlerAdapter {

	
	boolean supports(Object handler);

	
	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

	
	long getLastModified(HttpServletRequest request, Object handler);

}
                
 public class HttpRequestHandlerAdapter implements HandlerAdapter {

	@Override
	public boolean supports(Object handler) {
		return (handler instanceof HttpRequestHandler);
	}

	@Override
	@Nullable
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		((HttpRequestHandler) handler).handleRequest(request, response);
		return null;
	}

	@Override
	public long getLastModified(HttpServletRequest request, Object handler) {
		if (handler instanceof LastModified) {
			return ((LastModified) handler).getLastModified(request);
		}
		return -1L;
	}

}

image-20210623135018729

由于在程序掉用过程中Handler的类型丢失了,得到的Object对象无法直接调用方法,但是可以确定是几种handler具体实现之一,如果直接使用instance去if判断,代码臃肿,为了匹配原有功能,使用适配器,匹配上了就将原始类型还原在进行调用。

适配器优缺点

优点:

1.提高程序复用性,现有类复用但不需要改变

2.目标类和适配器类解耦,提高扩展性

缺点:

1.代码复杂程度变高,编写的难度大

2.降低代码可读性

桥接模式(Bridge Pattern)

桥接模式主要目的是通过组合的方式建立两个类之间的关系,而不是继承。桥接模式核心在于解耦抽象和实现。

桥接模式的角色

抽象(Abstraction): 该类持有一个实现角色的引用,抽象角色的方法需要去调用实现角色的实现。抽象角色一般是抽象类。

修正对象(RefinedAbstraction): Abstraction的实现,是关键的桥接对象,通过它完成抽象角色和实现类的关联

实现(Implementor):具体实现的操作定义,提供给Abstraction使用,该类一般为接口或者抽象类

具体实现(ConcreteImplementor) : Implementor 的具体实现

image-20210623141723291

//抽象对象
public class Abstraction {
    protected Implementor implemntor;

    public Abstraction (Implementor implementor) {
        this.implemntor = implementor;
    }

    public void operation(){
        //执行抽象类的逻辑
        //抽象方法掉用具体实现方法
        this.implemntor.operationImpl();
        //执行抽象类的逻辑
    }
}
//操作对象
public interface Implementor {
    void operationImpl();
}
//具体实现
public class ConcreteImplementorA implements Implementor{
    public void operationImpl() {
        System.out.println("A实现");
    }
}

public class ConcreteImplementorB implements Implementor{
    public void operationImpl() {
        System.out.println("B实现");
    }
}

//修正对象
**
 * 修正对象 实现抽象对象
 */
public class RefinedAbstraction extends Abstraction{
    //将具体实现和抽象对象关联
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    public void operation() {
        //可以再掉抽象对象的操作实现之前进行额外方法增强操作 before
        super.operation();
        //after
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        Implementor a = new ConcreteImplementorA();
        Implementor b = new ConcreteImplementorB();
        //创建修正对象
        Abstraction refinedAbstractionA = new RefinedAbstraction(a);
        Abstraction refinedAbstractionB = new RefinedAbstraction(b);
        //将抽象对象的逻辑和实现对象的逻辑通过修正对象实现了关联
        refinedAbstractionA.operation();
        refinedAbstractionB.operation();
    }
}
posted @ 2021-07-06 15:50  醉梦了红尘  阅读(199)  评论(0)    收藏  举报