享元模式
享元模式(Flyweight Pattern):又称之为蝇量模式,是对象池的一种实现。主要用于减少创建对象的数量,以减少内存占用和提高性能。类似于我们的数据库连接池和线程池。
这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
示例:我们通过购买火车票为例,来举例说明...
 package cn.liangyy.flyweight.one;
/** * 车票接口 */public interface ITicket {    /**     * 查询车票信息     */    void info();}
   复制代码
 
 package cn.liangyy.flyweight.one;
/** * 火车票类 */public class TrainTicket implements ITicket {    private String from;    //起点    private String to;      //终点
    public TrainTicket(String from,String to){        this.from = from;        this.to = to;    }
    /**     * 查询车票信息     */    @Override    public void info() {        System.out.println(from + "-->" + to + ":硬座:100元,硬卧:200元");    }}
   复制代码
 
 package cn.liangyy.flyweight.one;
import java.util.HashMap;import java.util.Map;
/** * 工厂类 * 管理享元对象,使用一个Map来存储对象,把火车票的起点和终点作为key, * 如果存在就取出来,否则就创建新对象,并且加到Map中。 */public class TicketFactory {    //缓存对象    private static Map<String,ITicket> CACHE_POOL = new HashMap<>();
    public static ITicket getTicketInfo(String from,String to){        String key = from + "-->" + to;        //如果对象存在缓存        if (TicketFactory.CACHE_POOL.containsKey(key)){            System.out.println("使用缓存");            return TicketFactory.CACHE_POOL.get(key);        }        //对象不存在缓存则创建一个对象,并加入缓存        System.out.println("未使用缓存");        ITicket ticket = new TrainTicket("成都","西宁");        CACHE_POOL.put(key,ticket);        return ticket;    }}
   复制代码
 
 package cn.liangyy.flyweight.one;
/** * 享元模式-测试 */public class TestTicket {    public static void main(String[] args) {        //首次创建对象        ITicket ticket = TicketFactory.getTicketInfo("成都","西宁");        ticket.info();        //使用缓存        ticket = TicketFactory.getTicketInfo("成都","西宁");        ticket.info();        //换了终点,,无法使用缓存        ticket = TicketFactory.getTicketInfo("成都","上海");        ticket.info();    }}
   复制代码
 
看到这儿,大家都会觉得这不就是一个简单的缓存使用嘛?确实如此,享元模式的核心思想就是使用缓存,它看起来和单例有点相似,单例模式关注的是整个对象只有一个实例,而享元模式关注的是状态,也就是说,同一个类中,只有状态一致。比如上述例子中成都到西宁的火车票,这就属于状态一致,所以使用缓存,而成都到上海又是另一个状态,所以无法使用缓存。那么大家会有疑问:享元模式的状态到底是什么呢?
享元模式的状态分为两种:
前面的例子中,我们可以把实例对象划分一下,比如上面车票的对象,可以把 from 和 to 两个属性作为可共享状态,不可改变。然后再新增一个属性用来对应座位,这个就属于外部状态。
状态示例:我们通过内部状态和外部状态改造上面的示例...
 package cn.liangyy.flyweight.two;
/** * 车票接口 */public interface IShareTicket {    /**     * 获取车票信息     */    void info();
    /**     * 设置车票座位     * @param seatType     */    void setSeat(String seatType);}
   复制代码
 
 package cn.liangyy.flyweight.two;
import java.math.BigDecimal;
/** * 火车票类 */public class TrainShareTicket implements IShareTicket {    private String from;    //内部状态    private String to;      //内部状态
    private String seatType = "站票";     //外部状态
    public TrainShareTicket(String from, String to) {        this.from = from;        this.to = to;    }
    /**     * 获取车票信息     */    @Override    public void info() {        System.out.println(from + "-->" + to + ":" + seatType + this.getPrice(seatType));    }
    /**     * 设置车票座位     *     * @param seatType     */    @Override    public void setSeat(String seatType) {        this.seatType = seatType;    }
    //获取不同座位的价格    private BigDecimal getPrice(String seatType) {        BigDecimal value = null;        switch (seatType) {            case "硬座":                value = new BigDecimal("100");                break;            case "硬卧":                value = new BigDecimal("200");                break;            default:                value = new BigDecimal("50");        }        return value;    }}
   复制代码
 
 package cn.liangyy.flyweight.two;
import java.util.HashMap;import java.util.Map;
/** * 工厂类 * 管理享元对象,使用一个Map来存储对象,把火车票的起点和终点作为key, * 如果存在就取出来,否则就创建新对象,并且加到Map中。 */public class TicketShareFactory {    //存储缓存对象    private static Map<String,IShareTicket> CACHE_POOL = new HashMap<>();
    public static IShareTicket getTicketInfo(String from,String to){        String key = from + "-->" + to;        //如果对象存在缓存        if (TicketShareFactory.CACHE_POOL.containsKey(key)){            System.out.println("使用缓存");            return TicketShareFactory.CACHE_POOL.get(key);        }        //对象不存在缓存则创建一个对象,并加入缓存        System.out.println("未使用缓存");        IShareTicket ticket = new TrainShareTicket(from,to);        CACHE_POOL.put(key,ticket);        return ticket;    }}
   复制代码
 
 package cn.liangyy.flyweight.two;
/** * 享元模式-测试 */public class TestShareTicket {    public static void main(String[] args) {        IShareTicket ticket = TicketShareFactory.getTicketInfo("成都","西宁");        ticket.setSeat("硬座");       //外部状态        ticket.info();      //首次创建对象        ticket = TicketShareFactory.getTicketInfo("成都","西宁");        ticket.setSeat("硬卧");       //外部状态        ticket.info();      //外部状态改变了,但是内部状态共享,依然可以使用缓存    }}
   复制代码
 
现在我们可以看到,将状态分离之后,外部状态的修改并不影响内部状态,也就是对象依然可以被缓存。
享元模式适用场景
享元模式优点减少对象的创建,降低了系统中对象的数量,故而可以降低系统的使用内存,提高效率。
享元模式缺点
评论