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

享元模式

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@15db9742
com.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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值