设计模式--flyweight模式

flyweight模式

名词解释

flyweigh表示蝇量级,是拳击比赛中最轻量的。用在设计模式里,将其翻译为享元模式,不
知道最开始是由谁翻译。享元,按照我的理解,元就是实例的意思,享,就是共享的意思。通
过共享,减少对象所占内存以及对象创建时间。

概述

Namecategoryintent
flyweightStructural用于重用有可能大量重复存在的细粒度对象,使这些大量的细粒度对象只存在一个

应用在

当系统中存在大量重复的对象时,可以考虑使用享元模式。该模式将对象放在一个容器里面,
当需要创建对象时,首先从容器中获取对象。若容器中不存在,则新建对象,并将其放在到容
器中。从而实现对象复用。这就像是缓存,区别于缓存的地方在于享元容器永远不失效,同时数量可控。

类图

代码

下面代码模拟的是一个搜索过程,在搜索中可以使用google,baidu,bing进行搜索,因为相同搜索引擎只需要创建一个,没有必要创建多个,所以利用到了享元模式。下面代码两次使用享元模式。

package com.liang.designpattern.flyweight;

import java.util.List;

public abstract class SearchEngine {

    private long timeoutInMs;
    private String name;

    public SearchEngine (Long timeoutInMs, String name) {
        this.timeoutInMs = timeoutInMs;
        this.name = name;
    }

    public List<Website> search(String keyword) {
        System.out.println(name + " search engine with timeout set to "  + timeoutInMs + "start to search");
        return doSearch(keyword);
    }

    protected abstract List<Website> doSearch(String keyword);
}
package com.liang.designpattern.flyweight;

import java.util.ArrayList;
import java.util.List;

public class Google extends SearchEngine {

    public Google(Long timeoutInMs, String name) {
        super(timeoutInMs, name);
    }

    @Override
    public List<Website> doSearch(String keyword) {
        List<Website> website = new ArrayList<Website>();
        website.add(WebsiteRepository.getInstance().getWebsite("title1", "url1", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title2", "url2", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title3", "url3", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title4", "url4", 1l));
        return website;
    }

}
package com.liang.designpattern.flyweight;

import java.util.ArrayList;
import java.util.List;

public class Bing extends SearchEngine {

    public Bing(Long timeoutInMs, String name) {
        super(timeoutInMs, name);
    }

    @Override
    public List<Website> doSearch(String keyword) {
        List<Website> website = new ArrayList<Website>();
        website.add(WebsiteRepository.getInstance().getWebsite("title1", "url1", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title2", "url2", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title4", "url4", 1l));
        return website;
    }

}
package com.liang.designpattern.flyweight;

import java.util.ArrayList;
import java.util.List;

public class Baidu extends SearchEngine {

    public Baidu(Long timeoutInMs, String name) {
        super(timeoutInMs, name);
    }

    @Override
    public List<Website> doSearch(String keyword) {
        List<Website> website = new ArrayList<Website>();
        website.add(WebsiteRepository.getInstance().getWebsite("莆田医院", "莆田医院", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title1", "url1", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title2", "url2", 1l));
        website.add(WebsiteRepository.getInstance().getWebsite("title3", "url3", 1l));
        return website;
    }
}
package com.liang.designpattern.flyweight;

public class Website {

    private String title;
    private String url;
    private long publishTimestamp;

    public Website(String title, String url, long publishTimestamp) {
        super();
        this.title = title;
        this.url = url;
        this.publishTimestamp = publishTimestamp;
    }

    public String getTitle() {
        return title;
    }

    public String getUrl() {
        return url;
    }

    public long getPublishTimestamp() {
        return publishTimestamp;
    }

    public String toString() {
        return String.format("[title:%s, url:%s, time:%d]", title, url, publishTimestamp);
    }
}
package com.liang.designpattern.flyweight;

import java.util.HashMap;
import java.util.Map;

public class WebsiteRepository {

    private  static WebsiteRepository repo = new WebsiteRepository();

    public Map<String, Website> websites = new HashMap<String, Website>();

    public static WebsiteRepository getInstance() {
        return repo;
    }

    public Website getWebsite(String name, String url, long timestamp) {
        if (!websites.containsKey(url)) {
            Website newsite = new Website(name, url, timestamp);
            websites.put(url, newsite);
            return newsite;
        }

        return websites.get(url);
    }

    public int howmanyWebsite() {
        return websites.size();
    }
}
package com.liang.designpattern.flyweight;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SearchEngineFlyweightFactory {

    private static final Map<String, SearchEngine> engines = new ConcurrentHashMap<>();

    public static SearchEngine getEngine(String name, long timeoutInMs, Class<? extends SearchEngine> clazz) {
        String key = name + timeoutInMs;
        SearchEngine engine = null;
        if (engines.get(key) == null) {
                try {
                    Constructor<? extends SearchEngine> cons =  clazz.getConstructor(Long.class, String.class);
                    engine = cons.newInstance(timeoutInMs, name);
                } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
                        | IllegalArgumentException | InvocationTargetException e) {
                    e.printStackTrace();
                }
                SearchEngine existing = engines.put(key, engine);
                if (existing != null) {
                    engine = existing;
                }
        } else {
            engine = engines.get(key);
        }

        return engine;
    }

    public static int howManyEngine() {
        return engines.size();
    }

}
package com.liang.designpattern.flyweight;

import java.util.List;

public class FlyWeightPatternClient {

    public static void main(String[] args) throws SecurityException, ClassNotFoundException {
        search("baidu", 1000L, Baidu.class, "keyword");
        search("google", 1000L, Google.class, "keyword");
        search("bing", 1000L, Bing.class, "keyword");

        search("baidu", 1000L, Baidu.class, "keyword");
    }

    private static void search(String name, long timeoutInms, Class<? extends SearchEngine> clazz, String keyword) {
        SearchEngine engine = SearchEngineFlyweightFactory.getEngine(name, timeoutInms, clazz);
        List<Website> websites = engine.search(keyword);
        renderWebsite(websites);
        System.out.println(SearchEngineFlyweightFactory.howManyEngine());
        System.out.println(WebsiteRepository.getInstance().howmanyWebsite());
    }

    public static void renderWebsite(List<Website> websites) {
        System.out.println("start to render " );
        for (Website website : websites) {
            System.out.println(website.toString());
        }
    }

}

真实案例

  1. jvm中的字符串常量池。相同的字符串会共享一个字符串对象;
  2. 在HystrixCommandKey.Factory类会存储所有线程group相同的HystrixCommandKey
  3. HystrixPropertiesFactory会存储线程熔断配置,这些都是享元模式的使用。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值