zoukankan      html  css  js  c++  java
  • 大话设计模式读书笔记(享元模式)

    人物:大鸟,小菜

    事件:小菜最近接了点私活,是一个做网站的外包,刚开始是为一个客户做,后来另一个客户也需要做一个类似的网站,后面客户多了这样代码虽然结构类似但是多多少少都有些不一样了,而且很费租用空间,后期更是难以维护,在小菜给大鸟倾诉完之后,大鸟为小菜提供了一种新的设计模式:享元模式


    享元模式:

    1.用代码设计小菜实例

    2.了解共享模式

    3.通过共享模式改进小菜实例并小结

    每个网站一个实例的设计实现

    WebSite类,网站:

    @Slf4j
    public class WebSite {
        private String name = "";
    
        public WebSite(String name) {
            this.name = name;
        }
    
        public void use() {
            log.info("网站分类:" + name);
        }
    }

    客户端代码:

    public class WebSiteClient {
        public static void main(String[] args) {
            WebSite fx = new WebSite("产品展示");
            fx.use();
            WebSite fy = new WebSite("产品展示");
            fy.use();
            WebSite fz = new WebSite("产品展示");
            fz.use();
            WebSite fl = new WebSite("博客");
            fl.use();
            WebSite fm = new WebSite("博客");
            fm.use();
            WebSite fn = new WebSite("博客");
            fn.use();
        }
    }

    小菜:这样就做出3个产品展示,3个博客的网站

    享元模式

    1.概念:运用共享技术有效地支持大量细粒度的对象

    2.结构图:

    3.代码示例:

    Flyweight类,是所有具体享元类的超类或接口

    public abstract class Flyweight {
        public abstract void Operation(int extrinsicstate);
    }

    ConcreteFlyweight类,为内部状态增加存储空间:

    @Slf4j
    public class ConcreteFlyweight extends Flyweight {
        @Override
        public void Operation(int extrinsicstate) {
            log.info("具体Flyweight: " + extrinsicstate);
        }
    }

    UnsharedConcreteFlyweight类,指那些不需要共享的Flyweight子类:

    @Slf4j
    public class UnsharedConcreteFlyweight extends Flyweight {
        @Override
        public void Operation(int extrinsicstate) {
            log.info("不共享的具体Flyweight: " + extrinsicstate);
        }
    }

    FlyweightFactory类,是一个享元工厂,用来创建和管理FlyweightFactory,主要是确保合理共享Flyweight:

    public class FlyweightFactory {
        private Hashtable flyweights = new Hashtable<>();
    
        public FlyweightFactory() {
            flyweights.put("X", new ConcreteFlyweight());
            flyweights.put("Y", new ConcreteFlyweight());
            flyweights.put("Z", new ConcreteFlyweight());
        }
    
        public Flyweight getFlyweight(String key) {
            return (Flyweight)flyweights.get(key);
        }
    }

    客户端代码:

    public class WebSiteClient {
        public static void main(String[] args) {
            int extrinsicstate = 22;
    
            FlyweightFactory f = new FlyweightFactory();
    
            Flyweight fx = f.getFlyweight("X");
            fx.Operation(--extrinsicstate);
    
            Flyweight fy = f.getFlyweight("Y");
            fy.Operation(--extrinsicstate);
    
            Flyweight fz = f.getFlyweight("Z");
            fz.Operation(--extrinsicstate);
    
            UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();
    
            uf.Operation(--extrinsicstate);
        }
    }

    享元模式结合小菜实例

    网站抽象类:

    @Slf4j
    public abstract class WebSite {
        public abstract void use();
    }

    具体网站类:

    @Slf4j
    public class ConcreteWebSite extends WebSite {
        private String name = "";
    
        public ConcreteWebSite(String name) {
            this.name = name;
        }
    
        @Override
        public void use() {
            log.info("网站分类:" + name);
        }
    }

    网站工厂类:

    public class WebSiteFactory {
        private Hashtable flyweights = new Hashtable();
    
        public WebSite getWebSiteCategory(String key) {
            if (!flyweights.containsKey(key)) {
                flyweights.put(key, new ConcreteWebSite(key));
            }
            return (WebSite) flyweights.get(key);
        }
    
        public int getWebSiteCount() {
            return flyweights.size();
        }
    }

    客户端代码:

    public class WebSiteClient {
        public static void main(String[] args) {
            WebSiteFactory f = new WebSiteFactory();
    
            WebSite fx = f.getWebSiteCategory("产品展示");
            fx.use();
    
            WebSite fy = f.getWebSiteCategory("产品展示");
            fy.use();
    
            WebSite fz = f.getWebSiteCategory("产品展示");
            fz.use();
    
            WebSite fl = f.getWebSiteCategory("博客");
            fl.use();
    
            WebSite fm = f.getWebSiteCategory("博客");
            fm.use();
    
            WebSite fn = f.getWebSiteCategory("博客");
            fn.use();
        }
    }

    最后输出的结果:

    网站分类:产品展示
    网站分类:产品展示
    网站分类:产品展示
    网站分类:博客
    网站分类:博客
    网站分类:博客
    网站分类总数为2

    大鸟:这样算是基本实现了享元模式共享对象的目的,不管建几个网站,只要key相同,那么就一样,这里只体现了相同的部分,但实际中不同企业可能需要的网站功能同,但是不同公司的账号,数据都是不同的,那你有考虑过怎么处理么,我再给你讲讲享元模式的内部状态和外部状态。

    享元模式的内部状态和外部状态

        享元模式可以避免大量相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数外,基本都是相同的,如果能把参数移到类实例的外面,在方法调用时将它们传进来,就可以通过共享大幅度减少单个实例的数目。

        也就是说客户的状态就是外部状态,应该由专门的对象来处理。

    于是小菜出了第三版:

    1.代码结构图:

    2.代码示例:

    User类,用户类,用户网站的客户账号:

    @Data
    @Accessors(chain = true)
    public class User {
        private String name;
    }

    网站抽象类:

    @Slf4j
    public abstract class WebSite {
    //使用的方法需要传递用户对象
    public abstract void use(User user); }

    网站工厂类:

    public class WebSiteFactory {
        private Hashtable flyweights = new Hashtable();
    
        public WebSite getWebSiteCategory(String key) {
            if (!flyweights.containsKey(key)) {
                flyweights.put(key, new ConcreteWebSite(key));
            }
            return (WebSite) flyweights.get(key);
        }
    
        public int getWebSiteCount() {
            return flyweights.size();
        }
    }

    客户端代码:

    @Slf4j
    public class WebSiteClient {
        public static void main(String[] args) {
            WebSiteFactory f = new WebSiteFactory();
    
            WebSite fx = f.getWebSiteCategory("产品展示");
            User user1 = new User().setName("小菜");
            fx.use(user1);
    
            WebSite fy = f.getWebSiteCategory("产品展示");
            User user2 = new User().setName("大鸟");
            fx.use(user2);
    
            WebSite fz = f.getWebSiteCategory("产品展示");
            User user3 = new User().setName("娇娇");
            fz.use(user3);
    
            WebSite fl = f.getWebSiteCategory("博客");
            User user4 = new User().setName("老顽童");
            fl.use(user4);
    
            WebSite fm = f.getWebSiteCategory("博客");
            User user5 = new User().setName("桃谷六仙");
            fm.use(user5);
    
            WebSite fn = f.getWebSiteCategory("博客");
            User user6 = new User().setName("南海鳄神");
            fn.use(user6);
    
            log.info("网站分类总数为{}", f.getWebSiteCount());
        }
    }

    结果输出:

    网站分类:产品展示用户:小菜
    网站分类:产品展示用户:大鸟
    网站分类:产品展示用户:娇娇
    网站分类:博客用户:老顽童
    网站分类:博客用户:桃谷六仙
    网站分类:博客用户:南海鳄神
    网站分类总数为2

    3.享元模式的应用场景

    (1)理解:当一个应用程序使用了大量重复的对象,而这些大量的存储对象造成了很大开销时,享元模式就可以通过共享对象来避免创建过多对象。

    (2)举例:String常量池、数据库连接池、缓冲池等等,或者你要开发一款五子棋游戏,理论上一盘棋有361个空格要创建361个对象,但用了共享模式后,只用创建两个即可。

    (3)优点:减少了大量重复的代码,简化了代码的复杂的,而且减小了开销,节省了内存,提高了性能。

  • 相关阅读:
    mysql 开发基础系列7 流程函数与其它函数
    mysql 开发基础系列6 数值与日期函数
    html5 浏览器端数据库
    html5 响应式布局
    css 文本溢出显示省略号
    js 字符串的操作
    js 图片轮播(一)
    css 弹出层-透明层
    js选项卡
    js获取当前时间显示在页面上
  • 原文地址:https://www.cnblogs.com/wencheng9012/p/13454742.html
Copyright © 2011-2022 走看看