设计模式之——享元模式

一、基本介绍

享元模式(结构型):运用共享技术来有効地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

二、包含角色

1.抽象享元角色:为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。

2.具体享元角色:实现抽象享元角色中所规定的接口,为需要共享的对象。

3.非享元角色:不共享的外部状态,作为享元角色所需要的外部参数,以形参的方式传入。

4.享元工厂角色:负责创建和管理享元角色,一般用缓存管理这些对象。

三、案例及UML类图

案例说明:

          验证码主要分为常见验证码,即数字+字母的形式,和计算类型验证码,即15+10=?类型的, 本公司主要提供验证码服务,其它要使用该服务的公司通过调用接口去创建使用该验证码, 因为访问量高,所以需要使用缓存来管理这些对象,节省内存开销。

UML类图:

类Captcha:

public interface Captcha {

    /**
     * 享元角色的公共接口
     * @param captchaArgs 外部状态,即变化的部分,通过参数传递,可以为对象或其它的参数。
     */
    void product(CaptchaArgs captchaArgs);
}

说明:验证码接口,抽象享元角色,定义验证码公共接口。

类ComputeCaptcha:

public class ComputeCaptcha implements Captcha {

    @Override
    public void product(CaptchaArgs captchaArgs) {
        System.out.println("生成了一个宽度:"+captchaArgs.getWidth()+"," +
                "高度:"+captchaArgs.getHeight()+"复杂度:"+captchaArgs.getComplexity()+"的计算型验证码。");
    }
}

说明:计算型验证码类,具体享元角色,需要共享的类。

类NormalCaptcha:

public class NormalCaptcha implements Captcha {


    @Override
    public void product(CaptchaArgs captchaArgs) {
        System.out.println("生成了一个宽度:"+captchaArgs.getWidth()+"," +
                "高度:"+captchaArgs.getHeight()+"复杂度:"+captchaArgs.getComplexity()+"的常见验证码。");
    }
}

说明:常见的验证码,如输入字母和数字的,具体享元角色,需要共享的类。

类CaptchaArgs:

public class CaptchaArgs {


    public CaptchaArgs(Integer width, Integer height, String complexity) {
        this.width = width;
        this.height = height;
        this.complexity = complexity;
    }

    private Integer width;

    private Integer height;

    /**
     * 复杂度
     */
    private String complexity;


    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public String getComplexity() {
        return complexity;
    }

    public void setComplexity(String complexity) {
        this.complexity = complexity;
    }
}

说明:验证码参数类,非享元角色,用于接收验证码的外部变化参数。

类FlyweightFactory:

public class FlyweightFactory {

    /**
     * 享元角色的缓存,key是验证码的类型,都是单例的
     */
    private Map<Integer, Captcha> captchaMap = new ConcurrentHashMap<>();

    /**
     * 初始化时,先添加好其需要共享的享元角色
     */
    public FlyweightFactory() {
        //0表示正常验证码
        captchaMap.put(0,new NormalCaptcha());
        //1表示输入型验证码
        captchaMap.put(1,new ComputeCaptcha());
    }

    /**
     * 享元模式的获取,只返回缓存中的,做到共享。
     * @param type 类型,0是正常验证码。1是计算型验证码
     * @return 验证码类
     */
    public Captcha getCaptcha(int type) {
        if(captchaMap.keySet().contains(type)) {
            return captchaMap.get(type);
        }else {
            return null;
        }
    }

}

说明:验证码工厂,享元工厂,用一个缓存保存需要共享的对象,为外部提供需要共享的变量。

类FlyweightTest:

public class FlyweightTest {

    public static void main(String[] args) {
        FlyweightFactory flyweightFactory = new FlyweightFactory();
        //获取一个正常验证码
        Captcha captcha = flyweightFactory.getCaptcha(0);
        // 生成一个长宽为120且简单的正常验证码
        captcha.product(new CaptchaArgs(120,120,"简单"));
        //获取一个计算型验证码
        captcha = flyweightFactory.getCaptcha(1);
        // 生成一个长宽为200且复杂的计算型验证码
        captcha.product(new CaptchaArgs(200,200,"复杂"));
    }


}

说明:测试及客户端类。

 

四、适用场景

1.系统中存在大量相同或相似的对象,这些对象耗费大量的内存资源。

2.常见的缓存

 

五、其它

注意:由于享元模式需要额外维护一个保存享元的数据结构,所以应当在享元对象被使用得足够多时才值得使用享元模式。

发布了35 篇原创文章 · 获赞 61 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/m0_37914588/article/details/103906382