结构性模式(三):代理模式、享元模式

2020-03-25  本文已影响0人  JBryan

1、代理模式

在不改变原始类(或叫被代理类)的情况下,通过引入代理类来给原始类附加功能。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。

1.1、实例说明

在某个应用软件中,需要记录业务方法的调用日志,在不修改现有业务类的基础上为每一个类提供一个日志记录代理类,如在业务方法method()调用之前输出“方法method()”被调用,调用之后如果没有异常,则输出“方法method()调用成功”,否则输出“method()调用失败”。在代理类中调用真实业务类的业务方法,使用代理模式设计该日志记录模块的结构,绘制类图并编程模拟实现。

1.2、实例类图
代理模式.jpg
1.3、实例代码
package com.ljessie.designpattern.structural.proxy;

public interface AbstractLog {
     void method();
}

public class BusinessClass implements AbstractLog {
    @Override
    public void method() {
        System.out.println("真实业务方法!");
    }
}

public class LoggerProxy implements AbstractLog {

    private BusinessClass businessClass;

    public LoggerProxy(){
        businessClass = new BusinessClass();
    }

    @Override
    public void method() {
        System.out.println("方法method()被调用!");
        try{
            businessClass.method();
            System.out.println("方法method()调用成功!");
        }catch (Exception e){
            System.out.println("方法method()调用异常!");
        }
    }
}

public class Client {
    public static void main(String[] args) {
        AbstractLog al = new LoggerProxy();
        al.method();
    }
}

代理模式在Spring AOP中的应用可参考:https://www.jianshu.com/p/58eb4b0a8a85

2、享元模式

所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。具体来讲,当一个系统中存在大量重复对象的时候,我们就可以利用享元模式,将对象设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。

实际上,不仅仅相同对象可以设计成享元,对于相似对象,我们也可以将这些对象中相同的部分(字段),提取出来设计成享元,让这些大量相似对象引用这些享元。

2.1、实例说明

使用享元模式设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。

2.2、实例类图
享元模式.jpg
2.3、实例代码
public class Coordinates {
    private int x;
    private int y;

    public Coordinates(int x,int y){
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

/**
 * 围棋棋子类,抽象享元类
 */
public abstract class IgoChessman {
    abstract String getColor();
    public void locate(Coordinates coordinates){
        System.out.println("棋子颜色:"+this.getColor()+",棋子位置:"+coordinates.getX()+","+coordinates.getY());
    }
}

/**
 * 具体享元类
 */
public class BlackIgoChessman extends IgoChessman {
    @Override
    String getColor() {
        return "黑色";
    }
}

/**
 * 具体享元类
 */
public class WhiteIgoChessman extends IgoChessman {
    @Override
    String getColor() {
        return "白色";
    }
}

public class IgoChessmanFactory {
    private static IgoChessmanFactory instance =
            new IgoChessmanFactory();
    private static Hashtable ht;
    private IgoChessmanFactory(){
        ht = new Hashtable();
        IgoChessman black = new BlackIgoChessman();
        IgoChessman white = new WhiteIgoChessman();
        ht.put("b",black);
        ht.put("w",white);
    }

    public static IgoChessmanFactory getInstance(){
        return instance;
    }

    public  IgoChessman getIgoChessman(String color){
        return (IgoChessman) ht.get(color);
    }

}

public class Client {
    public static void main(String[] args) {
        IgoChessman black1,black2,white1,white2;
        IgoChessmanFactory factory = IgoChessmanFactory.getInstance();
        black1 = factory.getIgoChessman("b");
        black2 = factory.getIgoChessman("b");
        white1 = factory.getIgoChessman("w");
        white2 = factory.getIgoChessman("w");
        System.out.println("两颗黑棋是否相同:"+(black1==black2));
        System.out.println("两颗白棋是否相同:"+(white1==white2));
        black1.locate(new Coordinates(1,2));
        white1.locate(new Coordinates(2,4));
    }
}

运行结果:

两颗黑棋是否相同:true
两颗白棋是否相同:true
棋子颜色:黑色,棋子位置:1,2
棋子颜色:白色,棋子位置:2,4
上一篇 下一篇

猜你喜欢

热点阅读