(三)面向性能调优的Java设计模式

目录

3、面向代码调优的设计模式

本质:减少对象的创建,尽量使用已经创建的对象

3.1、singleton(单例模式)

强制client只能创建一个object,避免因为new操作所带来的时空性能损失,也便于复用。
这里写图片描述
举例

public class Singleton {
    private static final Singleton instance = null;
    private Singleton() {…}
    public static Singleton getInstance() {
        /* 通过判断,只创建一个实例 */
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
    // other operations and data
}

关于单例模式的判断和代理模式的例子,有类似之处,都是判断如果已经有了,则不再创建,直接返回,降低代价和空间。
Recall
state模式中,两个状态是static的,当返回新状态时,返回Statet2.instanceState1.instance,保证始终只有两个状态实例。

3.2、prototype(原型模式)

通过克隆而非new来创建object。
继承树
这里写图片描述
举例

/* 创建实现Cloneable接口的抽象类,作为原型 */
public abstract class Shape implements Cloneable {
    private String id;
    protected String type;
    abstract void draw();
    public String getType(){ return type; }
    public String getId() { return id; }
    public void setId(String id) { this.id = id;}
    /* 实现clone方法 */
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}
/* 继承原型类 */
public class Rectangle extends Shape {
    public Rectangle(){
        type = "Rectangle";
    }
    @Override
    public void draw() {
    ...
    }
}
/* 继承原型类 */
public class Square extends Shape {
    public Square(){
        type = "Square";
    }
    @Override
    public void draw() {
    ...
    }
}
/* 客户端 */
    Shape rectangle = new Rectangle();
    Shape square = new Square();
    /* 使用克隆 */
    Shape clonedShape1 = (Shape) rectangle.clone();
    Shape clonedShape2 = (Shape) square.clone();

分析,首先要实现一个原型抽象类,该抽象类实现Cloneable接口,重写Object clone()方法;然后两个继承原型的类,rectangle和square;客户端中创建分别创建两个原型子类的对象,之后再创建对象,直接使用对象的clone()方法获得对象即可。

需要注意的是Cloneableclone操作默认实现的是浅复制,对象内部的变量都是直接填充的,可能会出现内存泄露。

实现Cloneable接口时,仅仅实现Cloneable不够,还需要override clone()方法并将public。因为Object.clone()protected:它可以被同包(java.lang)下以及它
(java.lang.Object)的子类访问。自定义类无法直接使用Object.clone():没有访问权限(invisible),故需要override

3.3、flyweight(轻量模式)

该模式允许在应用中不同部分共享使用objects,降低大量objects带来的时空代价。
内部状态和外部状态,
内部特征:不管在什么场合使用该object,内部特征都不变;
外部特征:不是固定的,需要在不同场合分别计算并产生变化。
继承树
这里写图片描述
举例

/* 外特征 */
public enum Color {Red, Green, Blank, Blue, Yellow}
/* 可共享对象的抽象接口 */
public interface IAlien {
    String Shape = null; //内部特征
    String getShape();
    Color getColor(int madLevel); //外部特征
}
/* 可共享对象类,Large Shape */
class LargeAlien implements IAlien{
    private String shape = "Large Shape";
    public String getShape() {
        return shape;
    }
    /* 设置外部特征 */
    public Color getColor(int madLevel) {
        if (madLevel == 0)
            return Color.Green;
        else if (madLevel == 1)
            return Color.Red;
        else
            return Color.Blue;
    }
}
/* 可共享对象,Little Shape */
class LittleAlien implements IAlien {
    private String shape = "Little Shape";
    public String getShape() {
        return shape;
    }
    public Color getColor(int madLevel) {
        if (madLevel == 0)
            return Color.Red;
        else if (madLevel == 1)
            return Color.Blue;
        else
            return Color.Green;
    }
}
/* 工厂,可共享对象的索引,维护所有对象,根据client请求返回相应的对象 */
public class AlienFactory {
    private Map<String, IAlien> list = new HashMap<>();
    public void SaveAlien(String index, IAlien alien) {
        list.put(index,alien);
    }
    public IAlien GetAlien(String index) {
        return list.get(index);
    }
}
/* 客户端 */
    /* 工厂方法,保存两个对象 */
    AlienFactory factory = new AlienFactory();
    factory.SaveAlien("LargeAlien", new LargeAlien());
    factory.SaveAlien("LittleAlien", new LittleAlien());
    /* 根据索引从工厂取出对象 */
    IAlien a = factory.GetAlien("LargeAlien");
    IAlien b = factory.GetAlien("LittleAlien");
    /* 内部特征 */
    System.out.println("Showing intrinsic states...");
    System.out.println("Alien of type LargeAlien is " + a.getShape());
    System.out.println("Alien of type LittleAlien is " + b.getShape());
    /* 外部特征 */
    System.out.println("Showing extrinsic states...");
    System.out.println("Alien of type LargeAlien is " + a.getColor(0).toString());
    System.out.println("Alien of type LargeAlien is " + a.getColor(1).toString());
    System.out.println("Alien of type LittleAlien is " + b.getColor(0).toString());
    System.out.println("Alien of type LittleAlien is " + b.getColor(1).toString());

总体来看,有一个共享对象接口,以及两个实现接口的类,包括内部特征(已经确定)和外部特征(根据传入参数,确定特征);一个工厂方法,保存所有的共享对象,根据传入索引返回共享对象;客户端调用时,可以传入参数,选择不同的外在特征,使得一个共享对象可以表现出不同的外在特征,而内在特征相同。

3.4、object pool(对象池)

很多时候,object不用了就直接扔掉,需要时再new一个新object。对象复用:不要扔掉object,留着后续复用。
代价:原本可被GC的对象,现在要留在pool中,导致内存浪费——用空间换时间。
继承树
这里写图片描述
举例

    //vector pool,管理所有的实例对象
    public static VectorPoolMgr vectorPoolMgr = new VectorPoolMgr(25);
    ...
    public void someMethod( ) {
        //Get a new Vector. We only use the vector to do some stuff
        //within this method, and then we dump the vector (i.e., it
        //is not returned or assigned to a state variable)
        //so this is a perfect candidate for reusing Vectors.
        //Use a factory method instead of 'new Vector( )'
        /* 从vector pool中取出一个对象,而不是使用new */
        Vector v = vectorPoolMgr.getVector();
        /* 对对象的属性进行修改 */
        ... //do vector manipulation stuff
        //and the extra work is that we have to explicitly tell the
        //pool manager that we have finished with the vector
        /* 返回对象 */
        vectorPoolMgr.returnVector(v);
    }

类似一个工厂方法,对象池管理所有废弃的对象,当需要一个新的对象时,从对象池中出去即可,取出后可以对属性进行修改配置,然后返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值