享元模式定义
使用共享对象可有效地支持大量的细粒度的对象
对象的信息分为两个部分: 内部状态 与外部状态
内部状态:
内部状态是对象可共享出来的信息,存储在享元对象内部并目不会随环境改变而改变
外部状态:
外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状态
使用场景
系统中存在大量的相似对象
细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份
需要缓冲池的场景。
角色定义
Flyweight抽象享元角色:
它简单地说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。
ConcreteFlyweight一一>具体享元角色:
具体的一个产品类,实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是绝对不允许的.
UnsharedConcreteFlyweight一一>不可共享的享元角色:
不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。
FlyweightFactory一一享元工厂:
职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方法
需求背景
在我们每个人网上购物的时候,我们一般会把对自己感兴趣的商品添加到购物车,针对同一个商品属性相同的情况下购买了多个,因为每个商品对象的属性都是相同的,如果每次都创建一个新的商品对象,会造成资源的浪费和重复的操作,而像优惠券这种对象,则不能被共享,因为每个优惠券有独特的代码和折扣金额。
以下是使用享元模式实现购物车场景的Java代码:
Flyweight抽象享元角色:
public interface Item {
void display();
}
ConcreteFlyweight具体享元角色:
public class Product implements Item {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public void display() {
System.out.println("Product: " + name + ", Price: " + price);
}
}
UnsharedConcreteFlyweight不可共享的享元角色:
public class DiscountCoupon implements Item {
private String code;
private double discountAmount;
public DiscountCoupon(String code, double discountAmount) {
this.code = code;
this.discountAmount = discountAmount;
}
@Override
public void display() {
System.out.println("Discount Coupon: " + code + ", Discount Amount: " + discountAmount);
}
}
代码实现
FlyweightFactory享元工厂:
import java.util.HashMap;
import java.util.Map;
public class ItemFactory {
private static Map<String, Item> items = new HashMap<>();
public static Item getItem(String key, String name, double price) {
Item item = items.get(key);
if (item == null) {
item = new Product(name, price);
items.put(key, item);
}
return item;
}
}
购物车类:
import java.util.ArrayList;
import java.util.List;
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
public void addItem(String name, double price) {
Item item = ItemFactory.getItem(name, name, price);
items.add(item);
}
public void addDiscountCoupon(String code, double discountAmount) {
Item item = new DiscountCoupon(code, discountAmount);
items.add(item);
}
public void displayItems() {
for (Item item : items) {
item.display();
}
}
}
测试案例:
public class ShoppingCartTest {
@Test
public void testShoppingCart() {
ShoppingCart cart = new ShoppingCart();
cart.addItem("Shirt", 50.0);
cart.addItem("Pants", 100.0);
cart.addItem("Shoes", 80.0);
cart.addItem("Hat", 20.0);
cart.addDiscountCoupon("DISCOUNT10", 10.0);
cart.addDiscountCoupon("DISCOUNT20", 20.0);
cart.displayItems();
}
}
输出结果:
Product: Shirt, Price: 50.0
Product: Pants, Price: 100.0
Product: Shoes, Price: 80.0
Product: Hat, Price: 20.0
Discount Coupon: DISCOUNT10, Discount Amount: 10.0
Discount Coupon: DISCOUNT20, Discount Amount: 20.0
总结:
享元模式是一种优化性能的设计模式,通过共享相同状态的对象来减少内存占用。在购物车场景中,商品对象可以被共享,而优惠券对象则不能被共享,因为每个优惠券有独特的代码和折扣金额。享元工厂负责管理享元对象的创建和共享。测试案例的输出结果表明,购物车中的商品和优惠券都被正确地显示出来了。