1

当我谈Proxy与Adpater模式时,我谈些什么

前言

今天跟同事谈起了一道面试题:“Proxy模式跟Adpater模式的区别”,这两个设计模式都是很相似的模式,很多有点经验的程序员都可能会聊的头头是道,但是恐怕谈起一些设计上的细节可能就会卡壳,因此我写下了这篇文章,以此作为一个简短的回顾。

Adapter(适配器)模式

Adpater属于两种适应设计模式中的其中一种,另外一种是Iterator(迭代器)模式,下次有机会再仔细聊聊它。

设计模式的书很喜欢以‘电源适配器插头’作为适配器模式的范例范例,那么我们也从这个例子开始吧。

参与模式的角色

1. Target (适配接口)

暴露给调用方的接口,定义了被适配对象暴露的方法。(我们需要220V的电源)

2. Client (请求者)

实际需要使用接口的逻辑(某电器需要使用220V的电源)

3. Adaptee(被适配对象)

被适配者,包含了具体的实现,及可能不太合适调用方使用的方法。(110V的电源不合适现在所用的电器)

4. Adpater(适配器)

实际适配的实现,用继承的方式隐藏了被适配对象的实现,又以实现适配接口的方式暴露调用者适合的方法。

UML类图

image

范例代码

下面的代码实现了一个输出110V的电源,通过220V电源适配器,实现了一个符合22V标准接口的输出,提供给客户端的示范。

#  adpatee
public class Power110v {

    private int volte = 110;
    
    public Power110v(){
        System.out.print("the power is on at "+volte+"V");
    }
    
    public String get100vPower(){
        return volte;    
    }
    
}

# target
public interface Power220v {
    get220vPower(String input);
}

# adapter 
public PowerAdpater extends Power110v implemnts Power220v {
    
    public get220vPower(){
        volte = volte * 2;
        System.out.println("the power is on at "+volte+"V")
    }
    
}

#client
public class Main (){
    
    public static void main(String[] args){
    
        PowerAdapter pa = new PowerAdapter();
        pa.get220vPower();
        
    }
    
}

小结

Adapter模式适用于那些已有代码很稳定,但新调用方需要对部分代码进行调整,或者组合多个方法进行组合实现逻辑的情况下适用。可以尽量适用已有的稳定代码,只作适当的修改便可以完成新的逻辑功能。

Proxy模式

参与模式的角色

1. Client

使用proxy的角色,功能的调用方,下面的例子是Manager(经理)类。

2. Subject

定义了proxy角色与RealSubject的一致性接口,范例代码中,是Reportable(可汇报)接口,

3. Proxy

Proxy会处理来自Client的请求,可以处理的功能自己处理,不能处理的功能让RealSubject处理,范例代码是TeamLeader类。

4. RealSubject

RealSubject将会在Proxy缺乏功能时提供实现,跟Proxy一样实现同样的接口,范例代码中是TeamMember类。

UML

image

范例代码
public interface Reportable{
    public void setReportMatrial(String jobContent);
    public String getReportMatrial();
    public String getFeedback();
}

public TeamMember implements Reportable{
    String reportMatrial;
    
    public void setReportMatrial(String input){
        this.reportMatrial = input;
    }
    
    public String getReportMatrial(){
        return this.reportMatrial;
    }
    
    public String getFeedback(){
        return "Here is the report content ["+this.reportMatrial+"]";
    }
}
    
}

public TeamLeader implements Reportable{

    String reportMatrial;
    TeamMember member;
    
    public TeamLeader(String input){
        this.reportMatrial = input;
    }
    
    public void setReportMatrial(String input){
        if (member != null){
            member.setReportMatrial(input)
        }
        this.reportMatrial = input;
    }
    
    public String getReportMatrial(){
        return this.reportMatrial;
    }
    
    public String getFeedback(){
        if ( member != null ){
            return member.getFeedback();
        }
        member = new TeamMember();
        member.setReportMatrial(this.reportMatrial);
    }
    
    
}

public class Manager {
    public static void main(String[] args){
        TeamLeader tl = new TeamLeader("monthly report");
        tl.setReportMatrial("weekly report")
        String currentReportType = tl.getReportMatrial();
        // the manager forgot what kind report should receive
        System.out.println("the current report type is " + currentReportType);
        // the manager ask the teamleader for the report detail.
        System.out.println("get some report from team leader"tl.getFeedback());
    }
}

Proxy与Adpater的总结

相同点

两者头通过实现接口暴露实际逻辑给调用方,核心逻辑都在最内一层的类中。

不同点

Proxy实现subject类与proxy类,都是实现一样的接口,暴露一样的方法。Adpater模式则Adpater与Adpatee则不一定实现同样的方法。理论上Proxy模式的proxy类,也承担一部分的功能,当它无法实现调用功能时才会创建被代理的RealSubject类。Adpater类则原则上与Adpatee共存亡。

参考资料


kidult_coder
17 声望3 粉丝

写下一些可以让我思考的东西,总会有一些东西会让你更逼格(Something bigger than yourself)。