源码git地址 https://github.com/dlovetco/designMode
在项目中有可能我们会需要建立许许多多个类似的对象,这些对象之间的不同可能仅仅是参数不同。盲目地不断new会不断加重服务器负担,此时我们可以考虑复用一些对象。
问题提出
小明做外包要建立许多个网站。有博客类的,购物类的等等。同类的网站结构几乎差不多,不同的只是某些地方的数据,像一些账户信息,文字内容。用代码实现这个场景。
享元模式
运用共享技术有效地支持大量细粒度的对象。
package flyweight;
import java.util.HashMap;
import java.util.Map;
public class FlyWeight {
public static void main(String[] args) {
User ming = new User();
ming.setUsername("小明");
User gang = new User();
gang.setUsername("小刚");
//建立两个博客
Website blog1 = WebsiteFactory.getWebsite("博客");
blog1.show(ming);
Website blog2 = WebsiteFactory.getWebsite("博客");
blog2.show(gang);
//建立两个购物网站
Website shopping1 = WebsiteFactory.getWebsite("购物网站");
shopping1.show(ming);
Website shopping2 = WebsiteFactory.getWebsite("购物网站");
shopping2.show(gang);
System.out.println(WebsiteFactory.getWebsizeNum());
}
}
class WebsiteFactory {
private static Map<String, Website> websiteMap = new HashMap<>();
//检查有没有已存在同一类型的对象
public static Website getWebsite(String type) {
Website website = websiteMap.get(type);
if (website == null) {
website = new ConcreteWebsite(type);
websiteMap.put(type, website);
}
return website;
}
public static int getWebsizeNum() {
return websiteMap.size();
}
}
/**
* 网站接口
*/
interface Website {
//User是外部参数
void show(User user);
}
class ConcreteWebsite implements Website {
public ConcreteWebsite(String websiteType) {
this.websiteType = websiteType;
}
//网站类型
private String websiteType;
@Override
public void show(User user) {
System.out.println("网站分类:" + websiteType + " 用户名:" + user.getUsername());
}
}
class User {
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
private String username;
}
享元模式的特点就是使用一个额外的类来保存已创建的对象。当客户端试图新建对象时都会先查看一遍有没有已经建立好的相似的对象。每个对象不同地方就使用参数传入,如上述例子中的user信息类。这些变化的信息称之为外部状态,而每个对象中不会随着环境改变而改变的信息称之为内部状态。
应用场景:
一个应用程序中使用大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数的状态是外部状态,如果删除对象的外部状态,那么可以使用相对较少的共享对象取代很多组对象,此时可以考虑使用享元状态。
plantuml
@startuml
class WebsiteFactory{
Map<String, Website> websiteMap
getWebsite(String type)
getWebsizeNum()
}
Website <..* WebsiteFactory
interface Website{
{abstract}show(User user)
}
Website <|.. ConcreteWebsite
class ConcreteWebsite{
show(User user)
}
User <.. Website
class User{
String name
}
@enduml