• 享元模式


    享元模式定义
    英文定义:A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects
    中文定义:享元模式运用共享技术有效地支持大量细粒度的对象。



    享元模式UML图(来自Google图片)

    享元模式


    抽象享元(Flyweight)角色:是给实现享元提供的接口。


    详细享元(ConcreteFlyweight)角色:实现抽象角色。此对象必须是共享的,所含的状态必须是内部状态。
    不共享享元(UnSharedConcreteFlyweight)角色:此对象不可共享。不是全部实现抽象享元接口的的对象都要共享。此对象通常将ConcreteFlyweight作为组成元素。


    享元模式使用场景(摘自《大话设计模式》)
    在襄垣对象内部而且不会随环境改变而改变的共享部分,能够称为是享元对象的内部状态。随环境改变而改变的、不能够共享的状态就是外部状态了。其实,享元模式能够避免大量非常类似类的开销。

    在程序设计中。有时须要生成大量细粒度的类实例来表示数据。假设能发现这些实例除了几个參数外基本上都是同样的,有时就能够大幅度地降低须要实例化的类的数量。

    假设能把那些參数移到类实例的外面,在方法调用时将它们传递进来,就能够通过共享大幅度地降低单个实例的数目。也就是说,享元模式Flyweight运行时所须要的状态是有内部的也可能有外部的,内部状态存储于ConcreteFlyweight对象之中。而外部对象则应该考虑由client对象存储或计算,当调用Flyweight对象的操作时。将该状态传递给它。


    假设一个应用程序使用了大量的对象。而大量的这些对象造成了非常大的存储开销时就应该考虑使用。还有就是对象的大多数状态能够外部状态。假设删除对象的外部状态。那么能够用相对较少的共享对象代替非常多组对象,此时能够考虑使用享元模式。

    在Java中。String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在Java中字符串常量都是存在常量池中的。Java会确保一个字符串常量在常量池中仅仅有一个拷贝。

    享元模式源代码演示样例

    享元模式原型

    public abstract class FlyWeight {
        public abstract void operation(int state);
    }
    
    public class ConcreteFlyWeight extends FlyWeight {
    
        @Override
        public void operation(int state) {
            System.out.println("Concrete Flyweight Information: " + state);
        }
    
    }
    
    public class FlyWeightFactory {
        private Map<String, FlyWeight> flyweightMap = new HashMap<String, FlyWeight>();
    
    
        public FlyWeightFactory() {
            // 这里我们初始化三个对象
            flyweightMap.put("X", new ConcreteFlyWeight());
            flyweightMap.put("X", new ConcreteFlyWeight());
            flyweightMap.put("X", new ConcreteFlyWeight());
        }
    
        public FlyWeight getFlyWeight(String key) {
            //当client要求生成一个对象时。工厂会检測是否存在此对象的实例,假设存在那么直接返回此对象实例,假设不存在就创建一个并保存起来,这点有些单例模式的意思。
            FlyWeight flyWeight = flyweightMap.get(key);
            if (null == flyWeight) {
                flyWeight = new ConcreteFlyWeight();
                flyweightMap.put(key, flyWeight);
            }
            return flyWeight;
        }
    }
    
    public class Client {
        public static void main(String[] args) {
            FlyWeightFactory factory = new FlyWeightFactory();
            FlyWeight flyWeightX = factory.getFlyWeight("X");
            flyWeightX.operation(2);
    
            FlyWeight flyWeightA = factory.getFlyWeight("A");
            flyWeightA.operation(1);
        }
    }

    一个实例:

    import java.util.concurrent.CopyOnWriteArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    // Instances of CoffeeFlavour will be the Flyweights
    class CoffeeFlavour {
      private final String name;
    
      CoffeeFlavour(String newFlavor) {
        this.name = newFlavor;
      }
    
      @Override
      public String toString() {
        return name;
      }
    }
    
    // Menu acts as a factory and cache for CoffeeFlavour flyweight objects
    class Menu {
      private Map<String, CoffeeFlavour> flavours = new HashMap<String, CoffeeFlavour>();
    
      CoffeeFlavour lookup(String flavorName) {
        if (!flavours.containsKey(flavorName))
          flavours.put(flavorName, new CoffeeFlavour(flavorName));
        return flavours.get(flavorName);
      }
    
      int totalCoffeeFlavoursMade() {
        return flavours.size();
      }
    }
    
    class Order {
      private final int tableNumber;
      private final CoffeeFlavour flavour;
    
      Order(int tableNumber, CoffeeFlavour flavor) {
        this.tableNumber = tableNumber;
        this.flavour = flavor;
      }
    
      void serve() {
        System.out.println("Serving " + flavour + " to table " + tableNumber);
      }
    }
    
    public class CoffeeShop {
      private final List<Order> orders = new CopyOnWriteArrayList<Order>();
      private final Menu menu = new Menu();
    
      void takeOrder(String flavourName, int table) {
        CoffeeFlavour flavour = menu.lookup(flavourName);
        Order order = new Order(table, flavour);
        orders.add(order);
      }
    
      void service() {
        for (Order order : orders) {
          order.serve();
          orders.remove(order);    
        }
      }
    
      String report() {
        return "
    total CoffeeFlavour objects made: "
            + menu.totalCoffeeFlavoursMade();
      }
    
      public static void main(String[] args) {
        CoffeeShop shop = new CoffeeShop();
    
        shop.takeOrder("Cappuccino", 2);
        shop.takeOrder("Frappe", 1);
        shop.takeOrder("Espresso", 1);
        shop.takeOrder("Frappe", 897);
        shop.takeOrder("Cappuccino", 97);
        shop.takeOrder("Frappe", 3);
        shop.takeOrder("Espresso", 3);
        shop.takeOrder("Cappuccino", 3);
        shop.takeOrder("Espresso", 96);
        shop.takeOrder("Frappe", 552);
        shop.takeOrder("Cappuccino", 121);
        shop.takeOrder("Espresso", 121);
    
        shop.service();
        System.out.println(shop.report());
      }
    }
  • 相关阅读:
    简单dp总结
    一、极限总结
    最短路径之差分约束
    软工个人总结
    BETA事后总结
    BETA(7)
    BETA(6)
    BETA(5)
    Go 中的字符串相关操作
    Go 中的异常/错误处理
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7010083.html
Copyright © 2020-2023  润新知