『设计模式』写代码偷懒小技巧,程序开发大智慧--享元模式
享元模式
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式讲类的属性分为内外属性(状态),内属性(状态)可共享,通过内属性结合传入的外部属性使用不同的功能(如棋盘横纵坐标,文字的字号颜色等),当相同内属性对象存在时,重用现有对象,不存在该对象时创建该对象。
实现原理:
通过HashMap存储现有对象,并通过唯一字段判断内存中是否存在可共享的对象,如果存在即返回现有对象,不存在则创建对象并添加到HashMap中。
主要解决:
在有大量细粒度对象时需要被创建时,可能会占用大量内存,为了减少内存的使用量,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
(网上很多说是为了解决内存溢出,这里本人认为,解决内存溢出是减少内存用使用量带来的,此设计模式并不是为了解决内存溢出的问题而设计的,只是可以解决内存,主要目的还是减少内存使用量而且还是只是在有大量细粒度对象被创建时才会有效,不然也不会降低内存使用)
何时使用:
1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。
优点:
大大减少对象的创建,降低系统的内存,使效率提高。
缺点:
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
实现:
UML(大话设计模式):
上面UML是比较经典的,以下是对上面的UML图进行优化后的代码!
package 享元模式;
public interface Inter_Flyweight {
public void Operation(int extrinsicstate);
}
package 享元模式;
public class ConcreteFlyweight implements Inter_Flyweight{
//
@Override
public void Operation(int extrinsicstate) {
System.out.println("做一些具体的功能:"+extrinsicstate);
}
}
package 享元模式;
public class UnshareFlyweight implements Inter_Flyweight {
@Override
public void Operation(int extrinsicstate) {
// TODO Auto-generated method stub
System.out.println("不共享的的具体类:"+extrinsicstate);
}
}
package 享元模式;
import java.util.HashMap;
public class Flyweight_Factory {
private HashMap<String, Inter_Flyweight> flyweights = new HashMap<String, Inter_Flyweight>();
public Flyweight_Factory() {
flyweights.put("X", new ConcreteFlyweight());
flyweights.put("Y", new ConcreteFlyweight());
flyweights.put("Z", new ConcreteFlyweight());
}
public Inter_Flyweight getFlyweight(String s) {
if (flyweights.get(s) == null)
flyweights.put(s, new ConcreteFlyweight());
return flyweights.get(s);
}
}
package 享元模式;
public class Client {
public static void main(String[] args) {
int method =0; //外部状态
Flyweight_Factory Fac=new Flyweight_Factory();
Inter_Flyweight Fx=Fac.getFlyweight("x");
Fx.Operation(method++);
Inter_Flyweight Fy=Fac.getFlyweight("y");
Fy.Operation(method++);
Inter_Flyweight Fz=Fac.getFlyweight("z");
Fz.Operation(method++);
Inter_Flyweight FQ=Fac.getFlyweight("Q");
FQ.Operation(method++);
Inter_Flyweight UF=new UnshareFlyweight();
UF.Operation(method);
}
}
再举一个五子棋的例子,如果每一个棋子占用一个对象,那么下满的话需要上百个对象,我们可以利用享元模式:
package 享元模式_五子棋;
public class Loc {
private int x;
private int y;
public Loc(int x, int y) {
this.x = x;
this.y = y;
}
public String show()
{
return "("+x+","+y+")";
}
}
package 享元模式_五子棋;
public abstract class Chess {
public abstract void Place_Chess(Loc loc);
}
package 享元模式_五子棋;
public class Chess_Concrete extends Chess {
private String type;
@Override
public void Place_Chess(Loc loc) {
System.out.println(type+"落子:"+loc.show());
}
public Chess_Concrete(String type) {
this.type = type;
}
}
package 享元模式_五子棋;
import java.util.HashMap;
public class Chess_Factory {
private HashMap<String, Chess> chess_container=new HashMap<>();
public Chess get_Chess(String s)
{
if(!chess_container.containsKey(s))
{
chess_container.put(s, new Chess_Concrete(s));
}
return chess_container.get(s);
}
}
package 享元模式_五子棋;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=0;i<=10;i++)
{
String s="黑棋";
if(i%2==0) s="白棋";
Chess_Factory CF=new Chess_Factory();
Chess_Concrete cc=(Chess_Concrete) CF.get_Chess(s);
cc.Place_Chess(new Loc(i,i));
}
}
}
写在最后:
Name:风骨散人,目前是一名双非在校大学生,预计考研,热爱编程,热爱技术,喜欢分享,知识无界,希望我的分享可以帮到你!名字的含义:我想有一天我能有能力随心所欲不逾矩,不总是向生活低头,有能力让家人拥有富足的生活而不是为了生计而到处奔波。“世人慌慌张张,不过是图碎银几两。偏偏这碎银几两,能解世间惆怅,可让父母安康,可护幼子成长 …”
文章主要内容:
Python,C++,C语言,JAVA,C#等语言的教程
ACM题解、模板、算法等,主要是数据结构,数学和图论
设计模式,数据库,计算机网络,操作系统,计算机组成原理
Python爬虫、深度学习、机器学习
计算机系408考研的所有专业课内容
目前还在更新中,先关注不迷路。微信公众号,cnblogs(博客园),CSDN同名“风骨散人”
如果有什么想看的,可以私信我,如果在能力范围内,我会发布相应的博文!
感谢大家的阅读!😘你的点赞、收藏、关注是对我最大的鼓励!