Proxy代理模式

代理模式,为其他对象提供一种代理以控制对这个对象的访问

clipboard.png
看代码更清晰

//Main函数
public class Main {
    public static void main(String[] args) {
        Printable p = new PrinterProxy("Alice");
        System.out.println("Print by:"+p.getPrinterName());
        p.setPrinterName("Bob");
        System.out.println("Print by:"p.getPrinterName());
        p.print("Hello, world.");
    }
}

//Printable接口
public interface Printable {
    public abstract void setPrinterName(String name);   
    public abstract String getPrinterName();            
    public abstract void print(String string);      
}

//重点来了
//PrinterProxy代理类
public class PrinterProxy implements Printable {
    private String name;            
    private Printer real;           
    public PrinterProxy() {
    }
    public PrinterProxy(String name) {      
        this.name = name;
    }
    public synchronized void setPrinterName(String name) {  
        if (real != null) {
            real.setPrinterName(name);  
        }
        this.name = name;
    }
    public String getPrinterName() {    
        return name;
    }
    public void print(String string) {  
        realize();
        real.print(string);
    }
    private synchronized void realize() {   
        if (real == null) {
            real = new Printer(name);
        }
    }
}

//Printer 
public class Printer implements Printable {
    private String name;
    public Printer() {
        heavyJob("Printer,heavyJob");
    }
    public Printer(String name) {
        this.name = name;
        heavyJob("Printer‚(" + name + ")‚");
    }
    public void setPrinterName(String name) {
        this.name = name;
    }
    public String getPrinterName() { 
        return name;
    }
    public void print(String string) { 
        System.out.println("=== " + name + " ===");
        System.out.println(string);
    }
    private void heavyJob(String msg) {
        System.out.print(msg);
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.print(".");
        }
        System.out.println("end");
    }
}


讲到proxy就不得不提到decorator装饰模式。这两种模式很相似,经常会混淆。

Decorator装饰模式

装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。

clipboard.png

对于Component来说,是无需知道Decorator的存在,Decorator是从外类来扩展Componnent类的功能。
看代码

//Main
public class Main {
    public static void main(String[] args) {
        Display b1 = new StringDisplay("Hello, world.");
        Display b2 = new SideBorder(b1, '#');
        Display b3 = new FullBorder(b2);
        b1.show();
        b2.show();
        b3.show();
        Display b4 = 
                    new SideBorder(
                        new FullBorder(
                            new FullBorder(
                                new SideBorder(
                                    new FullBorder(
                                        new StringDisplay("hello")
                                    ),
                                    '*'
                                )
                            )
                        ),
                        '/'
                    );
        b4.show();
    }
}

//Display
public abstract class Display {
    public abstract int getColumns();               
    public abstract int getRows();                  
    public abstract String getRowText(int row);     
    public final void show() {                      
        for (int i = 0; i < getRows(); i++) {
            System.out.println(getRowText(i));
        }
    }
}

//Border
public abstract class Border extends Display {
    protected Display display;          
    protected Border(Display display) {
        this.display = display;
    }
}

//这里只举一个实现类的例子
public class SideBorder extends Border {
    private char borderChar;                       
    public SideBorder(Display display, char ch) {   
        super(display);
        this.borderChar = ch;
    }
    public int getColumns() {                      
        return 1 + display.getColumns() + 1;
    }
    public int getRows() {                          
        return display.getRows();
    }
    public String getRowText(int row) {             
        return borderChar + display.getRowText(row) + borderChar;
    }
}

Proxy && Decorator

GoF提到它们的区别时,说到:
这两种模式都描述了怎样为对象提供一定程度上的间接引用,它们的实现部分都保留了指向另一个对象的指针,向这个对象发送请求。但它们还是具有不同的设计目的。
Proxy模式构成一个对象并为用户提供一致的接口。但与Decoratro模式不同的是,Proxy模式不能动态的添加或分离性质,也不是为递归组合而设计的。它的目的是,当直接访问一个不方便或不符合需要时,为这个实体提供一个替代者。

Proxy从语义上来说,就是一个代理类,我不需要知道你具体是哪个类实现的,我只需要能够访问这个提供服务的代理对象就可以。另外,Proxy着重控制对象。
Decorator更注重于装饰。是将需要装饰的对象通过构造函数的方式传入。
比较一下上述代码。注意装饰器和代理的初始化位置和方式
//Proxy在执行前后可以再做其他事,增强能力,改变的是行为。
//Decorator 目的是为了改变print的内容,先get内容,在get内容的方法中进行修改。

Mediator 中介者模式

中介者模式,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立改变它们之间的交互。

clipboard.png

把对象之间复杂的耦合写到mediator中,让mediator与其他对象的关联是整齐统一的。从而提高可用性和扩展性。

mediator与facade之间的区别

都是是把复杂的东西隐藏起来,让别人看起来比较简单。都没有简单化。只是进行隐藏。【需要考虑代价】
mediator是把对象之间复杂的关系都联系起来。相当于集线器。把所有东西和集线器联系起来。逻辑更为复杂。【仔细衡量是否一定需要。否则会有很大复杂性。】
facade是把外面的东西和内部的东西分开简单化。类似于包装盒。不管内部多复杂,对外只需要一个接口,外部不需要关心内部是如何实现。

参考文献:

  1. 《大话设计模式》

  2. Decorator模式与Proxy模式的异同之我见

  3. 代理模式 & 装饰器模式 (Proxy & Decorator)


lsxj
1k 声望92 粉丝

因为热爱,所以执着。