精华内容
下载资源
问答
  • 享元模式介绍,包括应用场景,优缺点,模式结构,类图 以及 C++代码示例

    更多设计模式参看: 设计模式之模式概述(模式汇总)(C++实现)

    介绍

    所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象

    “不可变对象”指的是,一旦通过构造函数初始化完成之后,它的状态(对象的成员变量或者属性)就不会再被修改了。

    意图:

    享元模式(Flyweight Pattern): 运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。

    解决问题:

    在有大量对象时,有可能会造成内存溢出,把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

    实现概述:

    通过工厂模式,在工厂类中,可以通过一个 Map 来缓存已经创建过的享元对象,来达到复用的目的。

    要点:

    用 Map 存储对象,享元模式以共享的方式高效地支持大量细粒度对象的重用,享元对象能做到共享的关键是区分了内部状态(Intrinsic State)和外部状态(Extrinsic State)

    内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享

    外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。

    应用场景:

    当一个系统中存在大量重复对象的时候,如果这些重复的对象是不可变对象,就可以利用享元模式将对象设计成享元,在内存中只保留一份实例,供多处代码引用。

    不仅仅相同对象可以设计成享元,对于相似对象,也可以将这些对象中相同的部分(字段)提取出来,设计成享元,让这些大量相似对象引用这些享元,不同的地方作为外部状态传入对象中。

    在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。

    生活中场景

    棋子,比如围棋子,棋子与棋子之间除了颜色和位置,好像没什么不同了!也就是说,每个棋子对象的大部分状态都是一样的(形状、材料、质地等)。

    软件中场景

    JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。

    Python [CPython(Python 的 C 实现)]内部会对 -5 到 256 的整型维持一个数组, 起到一个缓存的作用。

    优点:

    • 享元模式通过享元池存储已经创建好的享元对象,实现相同或相似的细粒度对象的复用,大大减少了系统中的对象数量,节约了内存空间,提升了系统性能
    • 享元模式通过内部状态和外部状态的区分,外部状态相互独立,客户端可以根据需求任意使用。

    缺点:

    • 享元模式需要增加逻辑来取分出内部状态和外部状态,增加了编程的复杂度;

    模式结构

    角色

    • Flyweight(抽象享元类):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外部提供享元对象的内部状态数据,也可以通过这些方法设置外部状态;
    • ConcreteFlyweight(具体享元类):具体实现抽象享元类声明的方法,其实例称为享元对象;具体享元类中为内部状态提供存储空间。具体享元类通常可以结合单例模式来设计实现,为每个具体享元类提供唯一的享元对象
    • UnsharedConcreteFlyweight(非共享具体享元类):并不是所有抽象享元类的子类都需要被共享,可以将这些类设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。
    • FlyweightFactory(享元工厂类):用于创建并管理享元对象,针对抽象享元类编程,将各种具体享元类对象存储在一个享元池中,享元池一般设计为一个存储键值对的集合(或者其他类型的集合),可结合工厂模式设计。客户需要某个享元对象时,如果享元池中已有该对象实例,则返回该实例,否则创建一个新的实例,给客户返回新的实例,并将新实例保存在享元池中。

    类图

    在这里插入图片描述

    代码示例

    以围棋棋子为例,棋子除了颜色和坐标其他都一样

    Flyweight(抽象享元类):ChessPiece

    ConcreteFlyweight(具体享元类):BlackChessPiece WhiteChessPiece

    UnsharedConcreteFlyweight(非共享具体享元类):Coordinates

    FlyweightFactory(享元工厂类):ChessPieceFactory

    GitHub

    FlyweightPattern

    UnsharedConcreteFlyweight(非共享具体享元类)

    /// UnsharedConcreteFlyweight(非共享具体享元类):Coordinates
    class Coordinates {
    public:
        Coordinates(int x,int y) {
            this->x = x;
            this->y = y;
            std::cout << "Coordinates Hello, x = "  << x << " y = " << y << std::endl;
        }
        ~Coordinates() {
            std::cout << "Coordinates Bye, x = "  << x << " y = " << y << std::endl;
        }
        int getX() {
            return x;
        }
        void setX(int x) {
            this->x = x;
        }
        int getY() {
            return y;
        }
        void setY(int y) {
            this->y = y;
        }
    private:
        int x;
        int y;
    
    };
    

    Flyweight(抽象享元类)

    /// Flyweight(抽象享元类):ChessPiece
    class ChessPiece {
    public:
        virtual ~ChessPiece() = default;
        virtual std::string getColor() = 0;
        void display(Coordinates *coord) {
            std::cout << "棋子颜色:" << getColor()  <<  ",棋子位置:"  << "x = "  << coord->getX() <<  ",y = "  << coord->getY() <<  std::endl;
        };
    protected:
        ChessPiece() = default;
        std::string color;
    };
    

    ConcreteFlyweight(具体享元类)

    /// ConcreteFlyweight(具体享元类):BlackChessPiece  WhiteChessPiece
    class BlackChessPiece : public ChessPiece {
    public:
        BlackChessPiece() {
            std::cout << "BlackChessPiece Hello" << std::endl;
            color = "黑色";
        }
        ~BlackChessPiece() override {
                std::cout << "BlackChessPiece Bye" << std::endl;
        }
        std::string getColor() override{
            return color;
        }
    };
    
    class WhiteChessPiece : public ChessPiece {
    public:
        WhiteChessPiece() {
            std::cout << "WhiteChessPiece Hello" << std::endl;
            color = "白色";
        }
        ~WhiteChessPiece() override {
            std::cout << "WhiteChessPiece Bye" << std::endl;
        }
        std::string getColor() override{
            return color;
        }
    };
    

    FlyweightFactory(享元工厂类)

    /// FlyweightFactory(享元工厂类):ChessPieceFactory
    class ChessPieceFactory {
    public:
        static ChessPieceFactory *getInstance() {
            static ChessPieceFactory instance;
            return &instance;
        }
        ChessPiece *getChessPiece(const std::string& color) {
            return mapChessPiece[color];
        }
    private:
        ChessPieceFactory() {
            std::cout << "ChessPieceFactory Hello" << std::endl;
            mapChessPiece.insert(std::pair<std::string,ChessPiece *>("b",new BlackChessPiece()));
            mapChessPiece.insert(std::pair<std::string,ChessPiece *>("w",new WhiteChessPiece()));
        }
        ~ChessPieceFactory() {
            std::cout << "ChessPieceFactory Bye" << std::endl;
            auto  iter = mapChessPiece.begin();
            while(iter!=mapChessPiece.end()) {
                ChessPiece *chessPiece = iter->second;
                delete chessPiece;
                iter++;
            }
        }
    
        std::map<std::string,ChessPiece *> mapChessPiece;
    };
    

    测试

    int main() {
        ChessPiece *black1,*black2,*black3,*white1,*white2;
        ChessPieceFactory *factory;
    
        //获取享元工厂对象
        factory = ChessPieceFactory::getInstance();
    
        //通过享元工厂获取三颗黑子
        black1 = factory->getChessPiece("b");
        black2 = factory->getChessPiece("b");
        black3 = factory->getChessPiece("b");
        std::cout << "两颗黑子是否相同:" << (black1==black2) <<  std::endl;
    
        //通过享元工厂获取两颗白子
        white1 = factory->getChessPiece("w");
        white2 = factory->getChessPiece("w");
        std::cout << "两颗白子是否相同:" << (white1==white2) <<  std::endl;
    
        std::vector<Coordinates *> coordinates;
        //std::function<Coordinates *(Coordinates *)> func = [&coordinates](Coordinates *coord ) {
        auto func = [&coordinates](Coordinates *coord ) {
            coordinates.push_back(coord);
            return coord;
        };
        //显示棋子
        black1->display(func(new Coordinates(1,3)));
        black2->display(func(new Coordinates(2,6)));;
        black3->display(func(new Coordinates(4,7)));;
        white1->display(func(new Coordinates(5,8)));;
        white2->display(func(new Coordinates(4,1)));;
    
        for (auto & coordinate : coordinates) {
            delete coordinate;
        }
        return 0;
    }
    

    输出

    在这里插入图片描述

    个人能力有限,如有错误之处或者其他建议,敬请告知欢迎探讨,谢谢!

    展开全文
  • 最新学习了简单工厂模式, ... 使用简单工厂模式设计一个可以创建不同几何形状(如圆形、方形三角形等)的绘图工具,每个几何图形都具有绘制draw()擦除erase()两个方法,要求在绘制不支持的几何图形.

    最新学习了刘伟老师的设计模式:简单工厂模式,

    史上最全设计模式导学目录(完整版)_刘伟技术博客-CSDN博客

    工厂三兄弟之简单工厂模式(一)_刘伟技术博客-CSDN博客工厂三兄弟之简单工厂模式(二)_刘伟技术博客-CSDN博客工厂三兄弟之简单工厂模式(三)_刘伟技术博客-CSDN博客工厂三兄弟之简单工厂模式(四)_刘伟技术博客-CSDN博客

    做一下后面的练习题

    练习

    使用简单工厂模式设计一个可以创建不同几何形状(如圆形、方形和三角形等)的绘图工具,每个几何图形都具有绘制draw()和擦除erase()两个方法,要求在绘制不支持的几何图形时,提示一个UnSupportedShapeException。

    先分析问题: 首先是有图形工具,可以创建不同形状,工具里面有两个方法,绘制daw()和擦除erase()。

    首先定义一个抽象类Shape,并针对抽象类Shape定义一个工厂类ShapeFactory

    package com.pattern.simplefactory;
    
    public abstract class Shape {
        /**
         * 绘制方法
         */
        abstract void draw();
    
        /***
         * 擦除方法
         */
        protected void erase(){
            for (int i = 0; i < 10; i++) {
                System.out.println();
            }
        }
    }
    

    定义具体的形状

    package com.pattern.simplefactory;
    /**
     * 圆形
     */
    public class ShapeCircular extends Shape{
        @Override
        public void draw() {
            int r=8;//圆形的半径
            for (int y = 0; y <= 2 * r; y += 2) {//y的步长为2,改变y的步长可以将圆形变成椭圆
                int x = (int)Math.round(r - Math.sqrt(2 * r * y - y * y));
                int len = 2 * (r - x);
                for (int i = 0; i <= x; i++) {
                    System.out.print(' ');
                }
                System.out.print('*');
                for (int j = 0; j <= len; j++) {
                    System.out.print('*');
                }
                System.out.println('*');
            }
        }
    }
    
    package com.pattern.simplefactory;
    /**
     * 方形
     */
    public class ShapeSquare extends Shape{
        @Override
        void draw() {
            int i = 5;
            for (int j = 0; j <= i; j++) {
                for (int k = 0; k <= i; k++) {
                    System.out.print(" * ");
                }
                System.out.println();
            }
        }
    }
    
    package com.pattern.simplefactory;
    /**
     * 三角形
     */
    public class ShapeTriangle extends Shape{
        @Override
        void draw() {
            int i= 5;
            for (int j = 0; j <= i; j++) {
                int spea = (i-j);
                for (int k = 0; k < spea; k++) {
                    System.out.print(" ");
                }
                for (int k = 0; k < j; k++) {
                    System.out.print("*");
                }
                for (int k = 0; k < j-1; k++) {
                    System.out.print("*");
                }
                System.out.println();
            }
        }
    }
    

    然后创建具体的工厂类ShapeFactory,其中如果有不支持的图形就报UnSupportedShapeException错误。:

    package com.pattern.simplefactory;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 图形工厂
     */
    public class ShapeFactory {
        private static String Circular = "Circular";
        private static String Square = "Square";
        private static String Triangle = "Triangle";
    
        public static Shape getShape(String shapeStr){
            Shape shape = null;
            if(Circular.equals(shapeStr)){
                shape = new ShapeCircular();
            }else if(Square.equals(shapeStr)){
                shape = new ShapeSquare();
            }else if(Triangle.equals(shapeStr)){
                shape = new ShapeTriangle();
            }else{
                throw new UnSupportedShapeException();
            }
            return shape;
        }
    }
    

    最后定义一个UnSupportedShapeException类 继承RuntimeException

    package com.pattern.simplefactory;
    
    public class UnSupportedShapeException extends RuntimeException{
    }
    

    最后测试一下:

    package com.pattern.simplefactory;
    
    public class Client {
        public static void main(String[] args) {
            //打印方形
            Shape shape = ShapeFactory.getShape("Square");
            shape.draw();
            //打印三角形
            Shape shape1 = ShapeFactory.getShape("Triangle");
            shape1.draw();
            //打印圆形
            Shape shape2 = ShapeFactory.getShape("Circular");
            shape2.draw();
            //擦除
            shape2.erase();
        }
    }
    

    最后运行结果:

     然后再思考一下,在工厂里面如果多次调用同一种形状每次会new一个全新的Shape.并且每次创建的Shape本身也并没有什么差别。这里可以用享元模式的思路来做一下改善:

    这里给一个享元模式入口史上最全设计模式导学目录(完整版)_刘伟技术博客-CSDN博客

    享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。

    package com.pattern.simplefactory;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 图形工厂
     */
    public class ShapeFactory {
        private static String Circular = "Circular";
        private static String Square = "Square";
        private static String Triangle = "Triangle";
        private static Map<String,Shape> shapeMap = new HashMap<>();
    
        public static Shape getShape(String shapeStr){
            Shape shape = null;
            //享元模式
            if(shapeMap.containsKey(shapeStr)){
                shape = shapeMap.get(shapeStr);
                return shape;
            }
            if(Circular.equals(shapeStr)){
                shape = new ShapeCircular();
            }else if(Square.equals(shapeStr)){
                shape = new ShapeSquare();
            }else if(Triangle.equals(shapeStr)){
                shape = new ShapeTriangle();
            }else{
                throw new UnSupportedShapeException();
            }
            shapeMap.put(shapeStr, shape);
            return shape;
        }
    }
    

    展开全文
  • 文章目录建造者模式目的类图实现应用场景优点 建造者模式 目的 封装一个对象的构造过程,并允许按步骤构造。 引用:创建者模式又叫建造者模式,是将一个复杂的对象的构建与它的表示分离,使 得同样的构建过程可以...

    5. 建造者模式(Builder)

    目的

    封装一个对象的构造过程,并允许按步骤构造。
    引用:创建者模式又叫建造者模式,是将一个复杂的对象的构建与它的表示分离,使
    得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。

    类图


    实现

    产品类

    
    public class Bike { 
    
        private IFrame frame; 
        private ISeat seat; 
        private ITire tire; 
        
        public IFrame getFrame() { 
            return frame; 
        } 
        public void setFrame(IFrame frame) { 
            this.frame = frame; 
        } 
        public ISeat getSeat() { 
            return seat; 
        } 
        public void setSeat(ISeat seat) { 
            this.seat = seat; 
        } 
        public ITire getTire() { 
            return tire; 
        } 
        public void setTire(ITire tire) { 
            this.tire = tire; 
        } 
    } 
    

    Builder 类:

    // 抽象 builder 类 
    public abstract class Builder { 
        abstract void buildFrame(); 
        abstract void buildSeat(); 
        abstract void buildTire(); 
        abstract Bike createBike(); 
    } 
    

    ConcreteBuilder 类 :

    // 具体 builder 类 
    public class MobikeBuilder extends Builder{ 
        private Bike mBike = new Bike(); 
        @Override 
        void buildFrame() { 
            mBike.setFrame(new AlloyFrame()); 
        } 
        @Override 
        void buildSeat() { 
            mBike.setSeat(new DermisSeat()); 
        } 
        @Override 
        void buildTire() { 
            mBike.setTire(new SolidTire()); 
        } 
        @Override 
        Bike createBike() { 
            return mBike; 
        } 
    } 
    
    public class OfoBuilder extends Builder{ 
        private Bike mBike = new Bike(); 
        @Override 
        void buildFrame() { 
            mBike.setFrame(new CarbonFrame()); 
        } 
        @Override 
        void buildSeat() { 
            mBike.setSeat(new RubberSeat()); 
        } 
        @Override 
        void buildTire() { 
            mBike.setTire(new InflateTire()); 
        } 
        @Override 
        Bike createBike() { 
            return mBike; 
        } 
    } 
    

    指挥者类:

    public class Director { 
        private Builder mBuilder = null; 
        public Director(Builder builder) { 
            mBuilder = builder; 
        } 
        public Bike construct() { 
            mBuilder.buildFrame(); 
            mBuilder.buildSeat(); 
            mBuilder.buildTire(); 
            return mBuilder.createBike(); 
        } 
    }
    

    客户端使用:

    public class Click { 
        public static void main(String[] args) { 
            showBike(new OfoBuilder()); 
            showBike(new MobikeBuilder()); 
        } 
        private void showBike(Builder builder) {
            Director director = new Director(builder); 
            Bike bike = director.construct(); 
            bike.getFrame().frame(); 
            bike.getSeat().seat(); 
            bike.getTire().tire(); 
        } 
    } 
    

    应用场景

    • 需要生成的对象具有复杂的内部结构
    • 需要生成的对象内部属性本身相互依赖
    • 与不可变对象配合使用

    优点

    • 建造者独立,易扩展
    • 便于控制细节风险

    6. 原型模式(Prototype)

    当系统中需要大量创建相同或者相似的对象时,就可以通过“原型设计模式”来实现。原型模式是“创建型设计模式”中的一种。

    原型模式的核心思想是,通过拷贝指定的“原型实例(对象)”,创建跟该对象一样的新对象。简单理解就是“克隆指定对象”。

    这里提到的“原型实例(对象)”,就是被克隆的对象,它的作用就是指定要创建的对象种类

    目的

    使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象。

    类图


    原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:

    • 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
    • 重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。

    实现

    原型类

    public abstract class Prototype implements Cloneable{
        
        private String id;
        
        public Prototype(String id) {
            this.id = id;
        }
        
        public String getId() {
            return this.id;
        }
        
        public Prototype clone() throws CloneNotSupportedException {
        
            return (Prototype) super.clone();
            
        }
        
    }
    

    具体实现类

    public class CreateProtype extends Prototype{
        
        public CreateProtype(String id) {
            super(id);
        }
    }
    

    客户端代码

    public class JavaDemo {
        
        public static void main(String[] args) throws CloneNotSupportedException {
            
            Prototype p1 = new CreateProtype("1");
            Prototype p2 = p1.clone();
            System.out.println(p1 == p2);
        }
        
    }
    

    原型模式的注意事项

    • 使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。而单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
    • 深拷贝与浅拷贝Object类的clone方法只会拷贝对象中的基本的数据类型(浅拷贝),对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。例如:
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    
    class scratch {
        public static void main(String[] args) throws CloneNotSupportedException  {
            Prototype p1 = new CreateProtype("1");
            Prototype p2 = p1.clone();
            System.out.println(p1 == p2);
            System.out.println(p1);
            System.out.println(p2);
        }
    }
    
    abstract class Prototype implements Cloneable{
        private List<String> list;
        private String id;
    
        public Prototype(String id) {
            this.id = id;
            list = new ArrayList<>();
            list.add(id);
        }
    
        public String getId() {
            return this.id;
        }
    
        public List<String> getList() {
            return this.list;
        }
    
        public Prototype clone() throws CloneNotSupportedException {
            Prototype prototype = null;
            try{
                prototype = (Prototype)super.clone();
                Collections.copy(prototype.list, this.list);
            }catch(CloneNotSupportedException e){
                e.printStackTrace();
            }
            return prototype;
        }
    
    }
    
    class CreateProtype extends Prototype{
    
        public CreateProtype(String id) {
            super(id);
        }
    
        public String toString(){
            return this.getId().hashCode()+"++"+this.getList().hashCode();
        }
    }
    
    

    应用场景

    当代码不应该依赖于需要复制的对象的具体类时

    优点

    • 可以不耦和具体类的情况下克隆对象
    • 避免重复的初始化代码
    • 更方便的构建复杂对象

    7. 享元模式(Flyweight)

    目的

    利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。

    类图

    • Flyweight:享元对象
    • IntrinsicState:内部状态,享元对象共享内部状态
    • ExtrinsicState:外部状态,每个享元对象的外部状态不同

    实现

    public interface Flyweight {
        void doOperation(String extrinsicState);
    }
    
    public class ConcreteFlyweight implements Flyweight {
    
        private String intrinsicState;
    
        public ConcreteFlyweight(String intrinsicState) {
            this.intrinsicState = intrinsicState;
        }
    
        @Override
        public void doOperation(String extrinsicState) {
            System.out.println("Object address: " + System.identityHashCode(this));
            System.out.println("IntrinsicState: " + intrinsicState);
            System.out.println("ExtrinsicState: " + extrinsicState);
        }
    }
    
    public class FlyweightFactory {
    
        private HashMap<String, Flyweight> flyweights = new HashMap<>();
    
        Flyweight getFlyweight(String intrinsicState) {
            if (!flyweights.containsKey(intrinsicState)) {
                Flyweight flyweight = new ConcreteFlyweight(intrinsicState);
                flyweights.put(intrinsicState, flyweight);
            }
            return flyweights.get(intrinsicState);
        }
    }
    
    public class Client {
    
        public static void main(String[] args) {
            FlyweightFactory factory = new FlyweightFactory();
            Flyweight flyweight1 = factory.getFlyweight("aa");
            Flyweight flyweight2 = factory.getFlyweight("aa");
            flyweight1.doOperation("x");
            flyweight2.doOperation("y");
        }
    }
    
    Object address: 1163157884
    IntrinsicState: aa
    ExtrinsicState: x
    Object address: 1163157884
    IntrinsicState: aa
    ExtrinsicState: y
    

    对象只创建了一次。

    优点

    如果系统有大量类似的对象,可以节省大量的内存及CPU资源

    展开全文
  • 今天阿粉要跟大家分享的是结构型模式享元模式,既然享元模式是属于结构性模式中的一种,那自然是用来组织代码,调整相应的代码结构来达到效果的,下面我们一起来看一下吧。 享元模式首先常规操作,我们先看一下...

    每天早上七点三十,准时推送干货

    cc9e7a5c13e03a986fbc065ec27a4d56.png

    Photo by

    Joshua Earle

    on

    Unsplash

    Hello 大家好,我是鸭血粉丝,今天周六,你是在休息学习还是在加班呢?

    今天阿粉要跟大家分享的是结构型模式之享元模式,既然享元模式是属于结构性模式中的一种,那自然是用来组织代码,调整相应的代码结构来达到效果的,下面我们一起来看一下吧。

    abeee9330ee3295c77a0689dc9c947d5.png

    享元模式

    首先常规操作,我们先看一下什么是享元模式,维基百科解释:享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。

    关键字:减少内存,共享物件,外部数据

    简单点描述一下就是一批对象中既有相同的内容也有不同的内容,相同的内容采用共享的方式,不同的内容通过动态传递的方式,来尽量减少对象的产生。这里需要理解的一点是,这多个对象其实底层对应的是同一个对象,物理地址是一个。

    享元模式使用场景

    享元模式的使用场景还是比较多的,最常见的一个场景就是 Java JDK 里面的 String 字符串类,因为 JVM 中有常量池,常量池的实现就是一种享元模式,避免多个相同对象的存在。另外线程池以及很多用到缓冲池的地方都采用了享元模式,比如 Integer 类中默认缓存了-128 -127 之间的整数,等等场景。

    在演示享元模式之前,我们要先了解享元模式中涉及到的几个角色名称

    抽象享元类:通常是一个接口,主要对外提供修改内部数据的接口

    具体享元类:享元的实现类,通常存储在内存中,便于使用

    享元工厂类:对外创建具体享元类

    下面

    我们通过一个简单的示例来演示一下享元模式,我们创建一个接口类,然后写一个实现类,再通过一个工厂来创建享元类,相关代码如下:

    UML 图解

    2c9e5c1bad3b810451f8a7ac0f7bad51.png

    代码演示

    我们先创建一个接口类 IFlyweight.java,里面包含一个设置宽度的方法,如下

    b0a3e8d7d9d76bfaced3b1ea42a367d6.png

    然后编写一个实现类 FlyweightImpl.java 来实现接口,并且在构造函数中传递一个 Color 对象

    b625b7ebca6df0ad003ee99a2e9c7023.png

    第三步我们再编写一个工厂类 FlyweightFactory.java,里面有一个 Color 对象的本地缓存,对于相同的颜色只保存一个对象。

    b9d7f89ee3f6588c5ea3a27b59985e0c.png

    颜色辅助类 Color.java

    160388df76a6127072d95df173ced1d4.png

    最后写一个测试应用类 FlyweightDemo.java

    d6e4e946688c06acf11ccd6d5511fadc.png

    上面测试类中,我们分别定义了两种颜色的三个对象,由于相同颜色的对象已经被缓存了,所以我们输出的结果如下:

    输出结果

    1730a959b248cfcb22d71048d4b24187.png

    从上面的运行结果中,我们可以看出,flyweight0 与flyweight1 其实是同一个对象,虽然他们的 width 和 height 属性值不一样,但是他们的底层对应的是同一个对象本身。这就是享元模式的核心内容,通过共享变量,来减少对象的产生,从而减少内存的使用。

    总结

    今天跟大家分享了一下设计模式中的结构型模式之享元模式,享元模式在我们日常使用的框架和组件都有很广泛的应用,希望通过这篇文章能够帮助大家加深或者理解享元模式,欢迎大家一起讨论交流,谈谈你所知道的还有哪些框架和组件中使用到了享元模式。

    展开全文
  • Flyweight模式(享元)Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循一定的编程模式,才能使自己的...
  • 什么是享元模式 举个围棋的例子,围棋的棋盘共有361格,即可放361个棋子,现在要实现一个围棋程序,该怎么办呢?首先 要考虑的是棋子棋盘的实现,可以定义一个棋子的类,成员变量包括棋子的颜色,形状,位置等信息,...
  • 最近在继续iPhone业务的同时还需要重新拾起Android。在有些生疏的情况下,决定从Android源码中感悟一些Android的风格...Android中的Message、ParcelTypedArray都利用了享元模式。以Message为例,类图如下: 其中...
  • 设计模式享元模式

    2021-08-10 23:36:52
    享元模式是运用共享技术有效地支持大量细粒度的对象的设计模式。 由于是细粒度单位的共享,享元模式又叫蝇量模式。 原理图 注意:内部状态与外部状态 使用享元模式,一定要分清什么可以共享(内部状态),什么不能...
  • 一、装饰器模式 1、概述 定义:装饰器(Decorator)模式指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。比继承更有弹性,体现了开闭原则。 2、...
  • /*** @Auther: maxw* @Date: 2018/11/21 09:47* @Description:享元模式:“”就是分享之意,指一物被众人共享,而这也正是该模式的终旨所在。* 享元模式有点类似于单例模式,都是只生成一个对象来被共享使用。这里...
  • 设计模式享元模式、例子分析
  • 实际上对象拷贝的工具有很多种,比如apache BeanUtils、apache PropertyUtils、spring BeanUtils。在一些业务代码中现在经常看到的都是spring BeanUtils来进行对象拷贝。大部分情况下来说已经...1、原型模式就是从一
  • 享元模式就可以解决我们所说的问题,“享元”何为享元,就是共享对象。重复的对象,无需重复创建,节约了内存空间。 享元的定义与特点   享元模式的定义提出了两种边界的要求,一个是内部状态,一个是外部状态...
  • 享元模式:“”就是分享之意,指一物被众人共享,而这也正是该模式的终旨所在。享元模式有点类似于享元的目的是为了减少不会要额内存消耗,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,...
  • 一、摘要本篇我们将会讲述结构性模式中的另外一个非常有用的模式-享元模式享元模式的特点是,复用我们内存中已存在的对象,降低系统创建对象实例的性能消耗。在.NET下的值类型引用类型的内存分配机制,我这里就...
  • 目录用途享元模式 (Flyweight)运用共享技术有效地支持大量细粒度的对象。享元模式是一种结构型模式。结构图-享元模式结构图Flyweight: 它是所有具体享元类的超类或接口,通过这个接口,Flyweight 可以接受并作用于...
  • 享元模式的定义提到了细粒度共享对象,要求细粒度,那就很可能会产生大量相似对象,由此,在这里需要用到共享技术,来减少大量对象的产生,防止内存的大量消耗。这里引入来内部状态外部状态两个概念。内部状态...
  • 介绍:享元模式意思是说系统中含有很多相同的对象,这时候没有必要用这么多的相同的对象,既大量消耗内存又没有用,这个对象只要一个就可以了,大家共享一个对象,享元模式主要减少了对象的创建,以减少内存提高...
  • 享元模式的总结如下图(可点击放大): UML结构图如下: 示例: public class FlyweightTest { public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight ...
  • 享元模式(Flyweight Pattern):主要用于减少创建对象的数量,以减少内存占用提高性能。在面向对象程序的设计过程中,有时需要创建大量相似的对象实例。如果都创建将会消耗很多系统资源,它是系统性能提高的一个...
  • 享元模式 例子 报考系统。需要选择考试地点(选择框)、报考地点(选择框)、邮寄地址(输入框),还有其他信息。 做一个很小的改动,增加了一个子类,实现带缓冲池的对象建立,同时在工厂类上增加 了一个容器对象...
  • java 设计模式享元模式①①定义使用场景问题分析享元模式单例模式的区别外部状态内部状态角色分析内部状态代码实现外部状态代码实现 人生是需要奋斗的,只有你奋斗了,失败后才会问心无愧;人生是单行路,...
  • 设计模式 | 享元模式

    2021-04-08 23:25:56
    1 | 享元模式的概述 如果一个软件系统在运行时所创建的相同或相似的对象数量太多,将导致运行代价过高,带来系统资源浪费、性能下降等问题。 例如:在一个文本字符串中存在很多重复的字符,如果每一个字符都用一个...
  • 定义享元模式(FlyWeight),运用共享技术有效地支持大量细粒度的对象。与单例模式有些类似,都是生成一个对象以便共享使用,其目的是减少大量不必要的内存消耗。实现享元模式实现起来也相对简单,先来看代码:public ...
  • 享元模式与组合模式

    2021-09-11 22:13:30
    一、享元模式定义 享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于 享元模式要求能够共享的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 61,328
精华内容 24,531
关键字:

原型模式和享元模式区别