GOF23设计模式之享元模式

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

说简单些就是对现有对象的重用,但这个对象中要区别两部分,一部分称之为内部状态,一部分为外部状态。所谓内部状态就是不会随环境变化的即固定的不变的,可共享的。所谓外部状态就是会变化的,不能共享的。

举个简单的例子。比如设计一个围棋软件,一个棋子就是一个对象,要是每个棋子都做为一个单独的对象的话,那下一盘下来就得创建几百个对象之多(就棋子而言,不计算其他依赖对象)。虽然说这么几百个对服务器来说不是什么问题,得做软件追求的应该是以最少的资源可以得到最大的效益,也就是精益求精嘛,做好点总没有错。为了节约这些个对象的内存资源就要享元模式上场了。

首先,棋子都一样嘛除了颜色,所以棋子就是享元对象。而棋子只有黑白两色,这不就是上面说的内部状态嘛,就黑白两种,总不能下着下着变出红色棋子来吧。而下棋时每个黑棋或白棋的落点位置都是不确定的,所以这也就是上面说的外部状态。理清楚了这些就可以用代码实现下了。

先定义一个抽象享元类AbstractChess,其中定义了内部状态color属性,而外部状态ChessLocation因为是时刻会变化的所以由调用时传入。

package com.minant.flyweight;

/**
 * @ClassName AbstractChess
 * @Description TODO 抽象棋子类
 * @Author MinAnt
 * @Date 2020/5/26
 * @Version V1.0
 */
public abstract class AbstractChess {

    private String color;

    public abstract void show(ChessLocation location);

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

}
package com.minant.flyweight;

/**
 * @ClassName ChessLocation
 * @Description TODO 棋子的位置
 * @Author MinAnt
 * @Date 2020/5/26
 * @Version V1.0
 */
public class ChessLocation {
    int x;
    int y;

    public ChessLocation(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;
    }
}

具体的享元类就是做了一个简单的描述功能:

package com.minant.flyweight;

/**
 * @ClassName RealChess
 * @Description TODO 具体享元棋子类
 * @Author MinAnt
 * @Date 2020/5/26
 * @Version V1.0
 */
public class RealChess extends AbstractChess {

    @Override
    public void show(ChessLocation location) {
        System.out.println(getColor() + "棋子的位置在:【"+location.getX()+","+location.getY()+"】");
    }
}

最后还有一个核心的享元工厂类,其中用一个HashMap来维护享元对象,一个对外获取享元对象的方法,通过棋子颜色为键,返回相应的棋子对象,map所维护的也就是黑棋和白棋两个对象:

package com.minant.flyweight;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName ChessFactory
 * @Description TODO 享元工厂类
 * @Author MinAnt
 * @Date 2020/5/26
 * @Version V1.0
 */
public class ChessFactory {
    private static final String CHESS_COLORS[] = {"black", "white"};

    protected static Map<String, RealChess> chessMap = new HashMap<>();

    public static RealChess getChess(String color) {
        int index = Arrays.binarySearch(CHESS_COLORS,color);
        if(index<0) {
            return null;
        }
        RealChess exitChess = chessMap.get(color);
        if(null == exitChess) {
            RealChess realChess = new RealChess();
            realChess.setColor(color);
            chessMap.put(color, realChess);
            exitChess = realChess;
        }
        return exitChess;
    }

}

测试:

package com.minant.flyweight;

/**
 * @ClassName TestFlyWeight
 * @Description TODO 测试享元模式
 * @Author MinAnt
 * @Date 2020/5/26
 * @Version V1.0
 */
public class TestFlyWeight {
    public static void main(String[] args) {
        RealChess chessa = ChessFactory.getChess("black");
        RealChess chessb = ChessFactory.getChess("white");
        RealChess chessc = ChessFactory.getChess("black");
        RealChess chessd= ChessFactory.getChess("white");
        System.out.println(chessa);
        System.out.println(chessb);
        System.out.println(chessc);
        System.out.println(chessd);

        System.out.println("************修改外部不共享状态***********");
        chessa.show(new ChessLocation(1,2));
        chessb.show(new ChessLocation(1,3));
        chessa.show(new ChessLocation(1,5));
        chessb.show(new ChessLocation(3,2));
    }
}

运行结果:

可以从结果看出,黑棋始终是一个对象,白棋也始终是一个对象,变化的是棋子的位置状态,这就是享元模式。

Stay hungry stay foolish!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值