Java设计模式- 结构型设计模式-享元模式

Java设计模式- 结构型设计模式-享元模式

从这一专栏开始将学习设计模式,上课学习和自己总结归纳的笔记将总结出来供大家参考。
参考书籍:《设计模式就该这样学》

其他文章:

Java设计模式-UML类图Java设计模式-七大架构设计原则-开闭原则
Java设计模式-七大架构设计原则-依赖倒置原则Java设计模式-七大架构设计原则-单一职责原则
Java设计模式-七大架构设计原则-接口隔离原则Java设计模式-七大架构设计原则-最少知道原则(迪米特法则)
Java设计模式-七大架构设计原则-里氏替换原则和合成复用原则Java设计模式-创建型设计模式-简单工厂模式
Java设计模式-创建型设计模式-工厂方法模式(工厂模式)Java设计模式-创建型设计模式-抽象工厂模式
Java设计模式-创建型设计模式-建造者模式Java设计模式-创建型设计模式-原型模式
Java设计模式-创建型设计模式-单例模式Java设计模式-结构型设计模式-适配器模式
Java设计模式- 结构型设计模式-享元模式Java设计模式- 结构型设计模式-外观模式
Java设计模式- 结构型设计模式-桥接模式Java设计模式-结构型模式设计模式-组合模式
Java设计模式-行为型设计模式-观察者模式

一、结构型设计模式

在GOF23种设计模式中,有三种类型的设计模式,分别是:创建型设计模式、结构型设计模式、行为型设计模式

结构型设计模式有:代理模式、适配器模式、桥接模式、装饰模式、外观模式、享元模式、组合模式 7 种结构型模式。

​ 类结构型模式:关心类的组合,由多个类组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。

​ 对象结构型模式:关心类与对象的组合,通过关联关系,在一个类中定义另外一个类的实例对象,然后通过该对象调用相应的方法。

二、享元模式

1.享元模式定义

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

2.内部状态和外部状态

享元模式提出了两个要求:细粒度和共享对象。这里就涉及到内部状态和外部状态,既将对象的信息分为两部分:内部状态和外部状态。
内部状态:指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变。
外部状态:指对象得以依赖的一个标记,是随环境改变而改变的,不可共享的状态。

3.享元模式的特点

优点:

相同对象只要保存一份,降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

缺点:

为了使对象共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。需要分离出外部状态和内部状态,而且外部状态具有固有化性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

适用环境:

1.系统中有大量相似对象。

2.这些对象消耗大量内存。

3.这些对象的状态大部分可以外部化。

4.这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。

5.系统不依赖于这些对象身份,这些对象是不可分辨的。

4.享元模式的角色

抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
非享元(Unsharalbe Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具有享元的相关方法中。

享元工厂(Flyweight Factory)角色 :负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在,则创建一个新的享元对象。

5.享元模式的类图

在这里插入图片描述

6.享元模式的代码实现

6.1具体案例:

在这里插入图片描述

该软件公司开发人员通过对围棋软件进行分析发现,在图中,围棋棋盘中包含大量的黑子和白子,它们的形状、大小都一模一样,只是出现的位置不同而已。如果将每一个棋子都作为一个独立的对象存储在内存中,将导致该围棋软件在运行时所需内存空间较大,如何降低运行代价、提高系统性能是需要解决的一个问题。为了解决该问题,现使用享元模式来设计该围棋软件的棋子对象。

类图如下:

在这里插入图片描述

具体代码实现:

1.抽象享元类 :IgoChessman

/**
 * 棋子抽象享元类
 * @author WxrStart
 * @create 2022-06-02 11:03
 */
public abstract class IgoChessman {
    public abstract String getColor();

    public void display(Coordinate coord) {
        System.out.println("棋子颜色:" + this.getColor()+",棋子位置:"+coord.getX()+","+coord.getY());
    }
}

2.具体享元类:BlackIgoChessman、WhiteIgoChessman

public class BlackIgoChessman extends IgoChessman {
    public String getColor() {
        return "黑色";
    }
}

public class WhiteIgoChessman extends IgoChessman {
    public String getColor() {
        return "白色";
    }
}

3.享元工厂类:IgoChessmanFactory

public class IgoChessmanFactory {
    private static volatile IgoChessmanFactory igoChessmanFactory = null;
    private static HashMap map;

    private IgoChessmanFactory() {
        map=new HashMap();
        IgoChessman black,white;
        black=new BlackIgoChessman();
        white=new WhiteIgoChessman();
        map.put("b",black);
        map.put("w",white);
    }

    public static IgoChessmanFactory getInstance() {
        if (igoChessmanFactory == null) {
            synchronized (IgoChessmanFactory.class) {
                if (igoChessmanFactory == null) {
                    igoChessmanFactory = new IgoChessmanFactory();
                }
            }
        }
        return igoChessmanFactory;
    }

    // 通过key获取存储在map中的享元对象
    public static IgoChessman getIgoChessman(String color) {
        return (IgoChessman) map.get(color);
    }
}

4.非享元角色:Coordinate

/**
 * 棋子坐标类
 * @author WxrStart
 * @create 2022-06-02 11:10
 */
public class Coordinate {
    private int x,y;

    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "Coordinate{" +
                "x=" + x +
                ", 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;
    }
}

5.客户端测试类

public class Client {

    public static void main(String[] args) {
        IgoChessman black1, black2, black3, white1, white2;
        IgoChessmanFactory factory;

        // 获取享元工厂对象
        factory = IgoChessmanFactory.getInstance();

        // 通过享元工厂获取3颗黑子
        black1 = factory.getIgoChessman("b");
        black2 = factory.getIgoChessman("b");
        black3 = factory.getIgoChessman("b");
        System.out.println("判断两颗黑子是否相同:" + (black1 == black2));

        // 通过享元工厂获取2颗白子
        white1 = factory.getIgoChessman("w");
        white2 = factory.getIgoChessman("w");
        System.out.println("判断两颗白子是否相同:" + (white1 == white2));

        // 显示棋子
        black1.display(new Coordinate(1,2));
        black2.display(new Coordinate(3,8));
        black3.display(new Coordinate(4,7));
        white1.display(new Coordinate(6,4));
        white2.display(new Coordinate(3,2));
    }
}

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值