23种设计模式11---享元模式

来源:互联网 发布:2017中国人工智能排名 编辑:程序博客网 时间:2024/06/06 02:50

享元模式

Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意。享元模式是对象的结构模式。享元模式以共享的方式高效地支持大量的细粒度对象。

   顾名思义:共享元对象。如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用创建新的对象。
享元模式是为数不多的、只为提升系统性能而生的设计模式。它的主要作用就是复用大对象(重量级对象),以节省内存空间和对象创建时间。

角色


1、Flyweight:享元接口,通过这个接口Flyweight可以接受并作用于外部状态。通过这个接口可以传入外部的状态,在享元对象的方法处理中可能会使用这些外部的数据。

2、ConcreteFlyweight:具体的享元实现对象,必须是共享的,需要封装Flyweight的内部状态。

3、UnshareConcreteFlyweight:非共享的享元实现对象,并不是所有的Flyweight实现对象都需要共享。非共
享的享元实现对象通常是对享元对象的组合对象。

4、FlyweightFactoty:享元工厂,主要用来创建并管理共享的享元对象,并对外提供访问共享享元的接口。

5、Client: 享元客户端,主要的工作就是维持一个对Flyweight的引用,计算或存储享元的外部状态,当然这里可访问共享和不共享的Flyweight对象。

一、代码实现

1.1、享元接口

/**享元接口:通过这个接口,接受并作用于外部状态通过这个接口可以传入外部状态,在享元的对象方法处理中可能用到这些外部数据 */public interface ChessFlyWeight {    /**     * 设置棋子的颜色     * @param color     */    void setColor(String color);    /**     * 获取棋子的颜色     * @return     */    String getColor();    void display(Coordinate coordinate);}

1.2、具体享元对象

/**具体享元对象: 具体的享元实现对象,必须是共享的,需要封装FlayWeight的内部状态 */public class ConcreateChess implements ChessFlyWeight{    private String color;    public ConcreateChess(String color) {        super();        this.color = color;    }    @Override    public void setColor(String color) {        this.color = color;    }    @Override    public String getColor() {        return this.color;    }    @Override    public void display(Coordinate coordinate) {        System.out.println("棋子的颜色:"+this.color);        System.out.println("棋子的位置:"+coordinate.getX()+"----"+coordinate.getY());    }}辅助类public class Coordinate {    private int x, y;    public Coordinate(int x, int y) {        this.x = x;        this.y = y;    }    public int getX() {        return x;    }    public int getY() {        return y;    }}

1.3、享元工厂

import java.util.HashMap;import java.util.Map;/**享元工厂:主要用来创建并管理共享的享元对象,并对外提供访问共享享元的接口 */public class ChessFlyWeightFactory {    //享元池    private static Map<String, ChessFlyWeight> map= new HashMap<String,ChessFlyWeight>();    public ChessFlyWeight getChess(String color) {        if (map.get(color) == null) {            ChessFlyWeight chessFlyWeight = new  ConcreateChess(color);            map.put(color, chessFlyWeight);            return chessFlyWeight;        }else {            return map.get(color);        }    }}

1.4、测试

public class Test {    public static void main(String[] args) {        ChessFlyWeightFactory chessFlyWeightFactory = new ChessFlyWeightFactory();        ChessFlyWeight cfw1 = chessFlyWeightFactory.getChess("红色");        ChessFlyWeight cfw2 = chessFlyWeightFactory.getChess("红色");        System.out.println(cfw1);        System.out.println(cfw2);         System.out.println("增加外部状态的处理===========");         cfw1.display(new Coordinate(10, 10));         cfw2.display(new Coordinate(20, 20));    }}输出:com.chb.k.FlyWeightDesignPattern.ConcreateChess@15db9742com.chb.k.FlyWeightDesignPattern.ConcreateChess@15db9742//cfw1和cfw2是同一个对象增加外部状态的处理===========棋子的颜色:红色棋子的位置:10----10棋子的颜色:红色棋子的位置:20----20

模式的优缺点

  模式的优点

      减少对象数量,节省内存空间。

  模式的缺点

      维护共享对象,需要额外开销。(比如:一个线程来回收垃圾)

思考

模式本质:分离和共享

开发中的应用场景:

享元模式由于其共享的特征,可以在任何“池”中操作,比如:线程池,数据库连接池。

String类的设计也是享元模式。

  在JAVA语言中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在JAVA中字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝。String a=”abc”,其中”abc”就是一个字符串常量。

public class Test {    public static void main(String[] args) {           String a = "abc";        String b = "abc";        System.out.println(a==b);    }}//输出结果:    true

这就说明a和b两个引用都指向了常量池中的同一个字符串常量”abc”。这样的设计避免了在创建N多相同对象时所产生的不必要的大量的资源消耗。

0 0
原创粉丝点击