【结构型设计模式】享元模式FlyWeight

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【结构型设计模式】享元模式FlyWeight,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

闲话

今天是周末,本来想偷一下懒,想想还是看一节设计模式吧
写的不好,欢迎大家一起讨论~

基本要点

1、使用场景:内存属于稀缺资源,如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存

2、核心

  • 以共享的方式支持大量细粒度对象的重用

  • 享元对象能做到共享的关键是区分了内部状态和外部状态
    内部状态:可以共享,不会随环境变化而改变
    外部状态:不可以共享,会随环境变化而改变

举例围棋软件来说
每个棋子都可以看成一个对象,颜色、形状、大小都能称为内部状态,因为这些是可共享的
但是位置每一个棋子都是独一无二的,是不可共享的,所以是外部状态

3、享元模式的实现

  • FlyweightFactory享元工厂类:创建并管理享元对象,享元池一般设计成键值对(可以理解为Map)
  • FlyWeight抽象享元对象:通常是一个接口或抽象类,用于声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态,例子中的棋子就可以看成这个
  • ConcreteFlyWeight具体享元类:将内部状态放在这,为内部状态提供成员变量进行存储
  • UnsharedConcreteFlyWeight非共享享元类:将外部状态放在这,不能被共享的子类可以设计成非共享享元类

4、享元模式优缺点
优点:极大减少了内存中对象的数量,节约系统资源,而且外部状态相对独立,不影响内部状态。
缺点:模式较为复杂,使程序逻辑复杂化;为了节省内存,共享了内部状态,分离出了外部状态,而读取外部状态时间较长,为了空间牺牲了时间。

实现代码

我们以上面的围棋系统为例子
首先,我们创建享元类和具体享元类

/**
 * 享元类,即FlyWeight抽象享元对象
 */
public interface ChessFlyWeight {
    // 获取棋子颜色(获取内部状态)
    String getColor();

    // 设置棋子坐标(设置外部状态)
    void display(Coordinate coordinate);
}

/**
 * ConcreteFlyWeight具体享元类:将内部状态放在这,提供成员变量进行存储
 */
class ChessConcreteFlyWeight implements ChessFlyWeight {
    // 为内部状态提供成员变量进行存储
    private String color;

    public ChessConcreteFlyWeight(String color) {
        this.color = color;
    }

    @Override
    public String getColor() {
        return color;
    }

    @Override
    public void display(Coordinate coordinate) {
        System.out.println("棋子颜色:" + color);
        System.out.println("棋子坐标:x= " + coordinate.getX() + "y=" + coordinate.getY());
    }
}

创建非共享享元类,将外部状态放在这里

/**
 * 外部状态相关类,UnsharedConcreteFlyWeight非共享享元类
 */
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 void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

创建享元工厂

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

/**
 * 享元工厂
 */
public class ChessFlyWeightFactory {
    // 享元池
    private static Map<String, ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();

    // 根据颜色获取棋子对象
    public static ChessFlyWeight getChess(String color) {
        // 如果有符合当前颜色要求的棋子对象,那就返回
        if (null != map.get(color)) {
            return map.get(color);
        } else {
            // 如果没有符合的对象就创建新的棋子对象,然后将其放入享元池中,在返回
            ChessFlyWeight chess = new ChessConcreteFlyWeight(color);
            map.put(color, chess);
            return chess;
        }
    }
}

模拟客户端

public class Client {
    public static void main(String[] args) {
        ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
        ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
        // chess1创建时,享元池里面并没有黑色棋子,所以创建了一个,获取chess2时,有了黑色棋子,所以可以直接去拿之前创建的那个对象
        System.out.println(chess1);
        System.out.println(chess2);

        System.out.println("增加外部状态处理===========");
        chess1.display(new Coordinate(10, 10));
        chess2.display(new Coordinate(20, 20));
    }
}

运行结果如图
在这里插入图片描述
如有错误,欢迎指正

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136812.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!