26 享元模式

1 定义

享元模式就是:运用共享技术有效地支持大量细粒度的对象。

2 内部状态与外部状态

  • 内部状态:在享元对象内部并且不会随环境改变而改变的共享部分。
  • 外部状态:随环境改变而改变的、不可以共享的状态。

享元模式Flyweight执行时所需的状态有内部的也有外部的,内部状态存储于ConcreteFlyweight对象中,外部状态则应该考虑有客户端对象存储或计算,当调用Flyweight对象的操作时,将该状态传递给它。

3 适用场景

  1. 如果一个程序使用了大量的对象,而大量的这些对象造成了很大的开销时就应该考虑使用。
  2. 对象的大多数状态是外部状态,如果删除对象的外部状态,就可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。
  • 实际中,使用实例
  1. 这段代码返回值是true,如果每次创建新字符串对象时,都需要创建一个新的字符串对象的话,内存开销会很大。所以第一个创建了字符串对象str1,下次在创建相同的字符串str2时只需要把它的引用指向“大话设计模式”,这样就实现了“大话设计模式”在内存中的共享。
    	String str1="大话设计模式";
        String str2="大话设计模式";
        if(str1==str2)
             System.out.println(true);
    
  2. 五子棋
    围棋的颜色是棋子的内部状态,位置是棋子的外部状态。一盘棋上有361个空位可以放棋子,那常规的面向对象方式编程,每盘棋可能有两三百个棋子对象产生。如果是有那个了享元模式来处理棋子,那么棋子对象可以减少到只有2个实例。

4 UML

26 享元模式_第1张图片

5 优点和缺点

5.1 优点

可以避免大量细粒度的对象,解决了对象开销的问题,同时又不影响客户程序。因为用了享元模式,就有了共享对象,实例总数就大大减少了,如果共享的对象越多,存储节约就越多,节约量随着共享状态的增多而增大。

5.2 缺点

  1. 使用享元模式需要维护一个记录了系统已有的所有享元的列表。
  2. 享元模式使得系统更加复杂。
  3. 为了使得对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。

因此,应该在有足够多的对象实例可供共享时才值得使用享元模式。

6 例子

6.1 场景

根据用户登录网站的类型,创建网站实例,从而同一类型的网站只存在一个实例。

6.2 UML

这里写图片描述

6.3 代码

Main

public class Main {
    public static void main(String[] args) {
        WebSiteFactory factory = new WebSiteFactory();
        ConcreteWebSite web1 = (ConcreteWebSite)factory.getWebSite("产品展示");
        web1.display(new User("李阳"));
        ConcreteWebSite web2 = (ConcreteWebSite)factory.getWebSite("合作商家");
        web2.display(new User("周青"));
        ConcreteWebSite web3 = (ConcreteWebSite)factory.getWebSite("经销商信息");
        web3.display(new User("黎洲"));
        ConcreteWebSite web4 = (ConcreteWebSite)factory.getWebSite("合作商家");
        web4.display(new User("李丽莉"));

    }
}

User

public class User {
    private String name;

    public User(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

WebSite

public abstract class WebSite {
    public abstract void display(User user);
}

ConcreteWebSite

public class ConcreteWebSite extends WebSite {

    private String webType ="";

    public ConcreteWebSite (String webType){
        this.webType =webType;
    }

    @Override
    public void display(User user) {
        System.out.println("网站分类:"+ webType +" 用户:"+user.getName());
    }
}

WebSiteFactory

public class WebSiteFactory {
    private Hashtable hashtable=new Hashtable<>();

    public WebSite getWebSite(String webType){
        if(!hashtable.contains(webType)){
            hashtable.put(webType,new ConcreteWebSite(webType));
        }
        return hashtable.get(webType);
    }

    public int getWebSiteCount(){
        return hashtable.size();
    }
}

运行结果

网站分类:产品展示 用户:李阳
网站分类:合作商家 用户:周青
网站分类:经销商信息 用户:黎洲
网站分类:合作商家 用户:李丽莉

你可能感兴趣的:(设计模式)