软件设计模式之路-----享元模式

 

在软件中,通常会有很多相同的角色。比如五子棋,一场对局中会有多个五子棋,若是用普通方法,一个五子棋就一个对象实例,这样将消耗大量的系统资源。像这种情况就可以使用享元模式了

享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

优点:

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

缺点:

  • 为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。 
  • 读取享元模式的外部状态会使得运行时间稍微变长。

享元模式的结构与实现

结构:

  1. 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。 
  2. 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。 
  3. 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。 
  4. 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

实现:

实现场景:LOL中的小兵,小兵有三类:炮兵,远程兵,近战兵

package com.wly.DesignPatterns;

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

/**
* @program: StudyDome
* @author: yuanzhang
* @create: 2020-12-27 15:41
**/
public class FlyweightStudy {
public static void main(String[] args) {
DogfaceFactory factory = new DogfaceFactory();
//创建小兵
System.out.println("创建小兵----------------------------------");
Dogface dogface = factory.getDogface(DogfaceType.Artillery);
Dogface dogface1 = factory.getDogface(DogfaceType.LongRangeDogface);
Dogface dogface2 = factory.getDogface(DogfaceType.MeleeDogface);
//给小兵赋予状态
System.out.println("小兵完整的信息----------------------------");
DogfaceAttribute dogfaceAttribute = new DogfaceAttribute(DogfaceType.Artillery);
DogfaceAttribute dogfaceAttribute1 = new DogfaceAttribute(DogfaceType.LongRangeDogface);
DogfaceAttribute dogfaceAttribute2 = new DogfaceAttribute(DogfaceType.MeleeDogface);

dogface.state(dogfaceAttribute);
dogface1.state(dogfaceAttribute1);
dogface2.state(dogfaceAttribute2);
//远程兵被攻击损失30血
dogfaceAttribute1.setBloodVolume(dogfaceAttribute1.getBloodVolume()-30);
System.out.println("远程兵被攻击后的状态------------------------------");
dogface1.state(dogfaceAttribute1);

}
}
class DogfaceType{
public static String Artillery ="artillery";

public static String LongRangeDogface ="longRangeDogface";

public static String MeleeDogface ="meleeDogface";
}
/**
* @Annotation:非享元角色:血量、攻击距离
* @Author: yuanzhang
* @Date: 15:45
*/
class DogfaceAttribute{
private Long BloodVolume;

private Long StrikingDistance;

public DogfaceAttribute(String name){
switch (name){
case "artillery":
//炮兵属性
this.BloodVolume = 900L;
this.StrikingDistance = 400L;
break;
case "longRangeDogface":
//远程兵属性
this.BloodVolume = 500L;
this.StrikingDistance = 450L;
break;
case "meleeDogface":
//近战兵属性
this.BloodVolume = 700L;
this.StrikingDistance = 100L;
break;
default:
break;
}
}

public void setBloodVolume(Long bloodVolume) {
BloodVolume = bloodVolume;
}

public Long getBloodVolume() {
return BloodVolume;
}

public void setStrikingDistance(Long strikingDistance) {
StrikingDistance = strikingDistance;
}

public Long getStrikingDistance() {
return StrikingDistance;
}
}
/**
* @Annotation:抽象享元:小兵
* @Author: yuanzhang
* @Date: 17:13
*/
interface Dogface{
void state(DogfaceAttribute dogfaceAttribute);
}
/**
* @Annotation:具体享元:炮兵
* @Author: yuanzhang
* @Date: 17:13
*/
class Artillery implements Dogface{
private String name;

Artillery(String name){
this.name = name;
System.out.println("炮兵被创建");
}

@Override
public void state(DogfaceAttribute dogfaceAttribute) {
System.out.println(name+"(血量:"+dogfaceAttribute.getBloodVolume()+",攻击距离:"+dogfaceAttribute.getStrikingDistance()+")");
}
}
/**
* @Annotation:具体享元:远程兵
* @Author: yuanzhang
* @Date: 17:12
*/
class LongRangeDogface implements Dogface{
private String name;

LongRangeDogface(String name){
this.name = name;
System.out.println("远程兵被创建");
}

@Override
public void state(DogfaceAttribute dogfaceAttribute) {
System.out.println(name+"(血量:"+dogfaceAttribute.getBloodVolume()+",攻击距离:"+dogfaceAttribute.getStrikingDistance()+")");
}
}
/**
* @Annotation:具体享元:近战兵
* @Author: yuanzhang
* @Date: 17:12
*/
class MeleeDogface implements Dogface{
private String name;

MeleeDogface(String name){
this.name = name;
System.out.println("近战小兵被创建");
}

@Override
public void state(DogfaceAttribute dogfaceAttribute) {
System.out.println(name+"(血量:"+dogfaceAttribute.getBloodVolume()+",攻击距离:"+dogfaceAttribute.getStrikingDistance()+")");
}
}
/** 
* @Annotation:享元工厂角色:兵工厂
* @Author: yuanzhang
* @Date: 17:11
*/ 
class DogfaceFactory{
private Map<String,Dogface> dogfaceMap = new HashMap<String,Dogface>();

public Dogface getDogface(String name){
Dogface dogface = dogfaceMap.get(name);
if (dogface==null){
DogfaceAttribute dogfaceAttribute = new DogfaceAttribute(name);
switch (name){
case "artillery":
dogface = new Artillery(name);
break;
case "longRangeDogface":
dogface = new LongRangeDogface(name);
break;
case "meleeDogface":
dogface = new MeleeDogface(name);
break;
default:
break;
}
dogfaceMap.put(name,dogface);
}

return dogface;
}
}

输出

创建小兵----------------------------------
炮兵被创建
远程兵被创建
近战小兵被创建
小兵完整的信息----------------------------
artillery(血量:900,攻击距离:400)
longRangeDogface(血量:500,攻击距离:450)
meleeDogface(血量:700,攻击距离:100)
远程兵被攻击后的状态
longRangeDogface(血量:470,攻击距离:450)

这个例子不太恰当,非享元角色应为小兵的动态血量,以及位置。不应该是固有的初始血量,和固定的攻击距离。

所以再做个总结理解一下享元模式:
享元模式就是对一些重复的对象,抽出其变化的数据来作为非享元角色。根据非享元角色的数据来确定一个新的对象。这样就不需要重复创建相同的对象,只需要改变其变化的状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值