Leisure Moment

乱花渐欲迷人眼,浅草才能没马蹄。最爱湖东行不足,绿杨阴里白沙堤。


  • Home

  • Archives

  • Tags

  • About

  • Sitemap

java_fx_property

Posted on 2016-12-18 | In java_fx

property的概念

一个property 通常是外部不可见的,在该类之外,我们只能通过get/set这些接口方法实现对其读与修改,我们对其实现细节(setter/getter)不关心也并不需要知道。但是通常我们(view)对它是否改变,从什么值改变成什么值十分关心(view)


the kinds of feature in property of java fx

  • 对于 fx 的property 都是可观察的(observable) 实现了observable 和observableValue接口
    observable接口
    1
    2
    3
    4
    public interface observable {
    void addListener(InvalidationListener listener);
    void removeListener(InvalidationListener listener);
    }

observalue接口

1
2
3
4
5
6
public abstract interface ObservableValue<T> extends Observable
{
public abstract void addListener(ChangeListener<? super T> paramChangeListener);
public abstract void removeListener(ChangeListener<? super T> paramChangeListener);
public abstract T getValue();
}

它们监听失效(invalid) 和 变化(change) 事件

  • Property 可以分为只读的以及可读写的。

    每个Property 类一般提供 : get()/set() and getValue()/setValue 针对primitive type(Read only property don't provide the set interface.)  getValue/SetValue 针对装箱类型
    

read-write property is easy to understand, you can read-write it in internal or outside.

  • 对于只读属性的认识. (read-only for outside and read-write internally)
    一个ReadOnlyXXXWrapper 类 包裹了两个类型,一个是只读的,一个是可读写的.
    1
    2
    3
    4
    5
    6
    7
    8
    ReadOnlyIntegerWrapper idWrapper = new ReadOnlyIntegerWrapper(100);
    ReadOnlyIntegerProperty id = idWrapper.getReadOnlyProperty();
    System.out.println("idWrapper:" + idWrapper.get());
    System.out.println("id:" + id.get());
    // Change the value
    idWrapper.set(101);
    System.out.println("idWrapper:" + idWrapper.get());
    System.out.println("id:" + id.get());

A Book Class 同时拥有只读属性和可读写属性的一个实体类

对于可读写属性抽象类型为XXXProperty, 实现类型通常SimpleXXXProperty.对于只读属性抽象类型通常是ReadOnlyXXXProeprty, 实现类型是ReadOnlyXXXWrapper.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Book {
private final StringProperty title = new SimpleStringProperty(this,"title", "Unknown");
private final DoubleProperty price = new SimpleDoubleProperty(this,"price", 0.0);
private final ReadOnlyStringWrapper ISBN = new ReadOnlyStringWrapper(this,"ISBN", "Unknown");
public Book() {}
public Book(String title, double price, String ISBN) {
this.title.set(title);
this.price.set(price);
this.ISBN.set(ISBN);
}
public final String getTitle() {
return title.get();
}
public final void setTitle(String title) {
this.title.set(title);
}
public final StringProperty titleProperty() {
return title;
}
public final double getprice() {
return price.get();
}
public final void setPrice(double price) {
this.price.set(price);
}
public final DoubleProperty priceProperty() {
return price;
}
public final String getISBN() {
return ISBN.get();
}
public final ReadOnlyStringProperty ISBNProperty() {
return ISBN.getReadOnlyProperty();
}
}


Lazily Instantiating Property Objects (充分优化内存,使用懒加载)

只有当需要item的weightProperty被需要的时候(weightProperty()被调用)初始化property.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Item {
private DoubleProperty weight;
private double _weight = 150;

public double getWeight() {
return (weight == null) ? _weight : weight.get();
}

public void setWeight(double newWeight) {
if (weight == null) {
_weight = newWeight;
} else {
weight.set(newWeight);
}
}

public DoubleProperty weightProperty() {
if (weight == null) {
weight = new SimpleDoubleProperty(this, "weight", _weight);
}
return weight;
}
}

Tips:
使用懒加载或者饥饿加载主要试情况而定, 一个拥有少量属性的类,并且基本你必定会用到属性,那么可以考虑饥饿加载,如果是封装的对象开销过大或者一个类里面封装了许多属性,只有少数会使用到时候可以考虑懒加载来优化内存。


Property Class Hierarchy

Paste_Image.png


最好将 property 的getter/setter 声明为final

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Book2 {
private final StringProperty title = new SimpleStringProperty(this,
"title", "Unknown");
public final StringProperty titleProperty() {
return title;
}
public final String getTitle() {
return title.get();
}
public final void setTitle(String title) {
this.title.set(title);
}
}

解析property 接口的方法

  1. bind(建立单向绑定)
    与一个来自于继承泛型T链的实现了observableValue接口的对象(一般为property)相绑定

    1
    void bind(ObservableValue<? extends T> observable);
  2. bindBidrectional(建立双向绑定)
    必须与同一类型建立双向绑定

    1
    void bindBidirectional(Property<T> other);

对property 对象添加Invalidation(失效)事件监听

1
2
3
4
5
6
7
8
9
10
11
12
main {
IntegerProperty counter = new SimpleIntegerProperty(100);
couter.set(100) // 会出发一个invalid事件
couter.set(101) // 不会触发,因为该属性已经失效
int value = couter.get() //使属性回复有效
couter.set(101) // 会再出发一个Invalid事件
// Add an invalidation listener to the counter property
counter.addListener(InvalidationTest::invalidated);
}
public static void invalidated(Observable prop) {
System.out.println("Counter is invalid.");
}

对property 对象添加change(值改变)事件监听

1
2
3
4
5
6
7
8
9
10
11
12
main {
IntegerProperty counter = new SimpleIntegerProperty(100);
// Add a change listener to the counter property
counter.set(101); // 产生changeEvent
counter.set(102); //产生changeEvent
counter.set(102); //不产生changeEvent
counter.addListener(ChangeTest::changed);
}
public static void changed(ObservableValue<? extends Number> prop,Number oldValue,Number newValue) {
System.out.print("Counter changed: ");
System.out.println("Old = " + oldValue + ", new = "+ newValue);
}

使用WeakListener来避免内存泄漏

应该在对某个property添加listener. 这样这些property中就有listener的强引用,这样这些listener就很难被回收。还有一种情况就是匿名的changlistener实现,会有外部的
对象的引用,如果外部对象包括比较占内存的view,就很容易出现这个问题。

1
2
3
4
5
6
ChangeListener<Number> cListener = create a change listener...
WeakChangeListener<Number> wListener = new WeakChangeListener(cListener);
// Add a weak change listener, assuming that counter is a property
counter.addListener(wListener);
......
cListener = null;//不需要改listener的时候


Hexo 文章帮助指南

Posted on 2016-10-18

一级标题

一个#

二级标题

二个#

三级标题

三个#

无序列表

  • 1 (*开头)
  • 2
  • 3

有序列表

  1. 1 (数字加.)
  2. 2
  3. 3
  4. 4

引用

例如这样(>)

插入连接

[google] (http://www.google.com)

插入图片

Mou icon
http://www.getcloudapp.com/

####
粗体是两个*包含
斜体是一个包含

代码框

需要用两个 ` 把中间的代码包裹起来

code


分割线
分割线的语法只需要另起一行,连续输入三个星号 *** 即可。


hexo

hexo 部署新change

hexo clean

hexo generate

hexo deploy

hexo new”postName” #新建文章

hexo new page”pageName” #新建页面

hexo generate #生成静态页面至public目录

hexo server #开启预览访问端口(默认端口4000,’ctrl + c’关闭server)

hexo deploy #将.deploy目录部署到GitHub

hexo help # 查看帮助

hexo version #查看Hexo的版本

数据库范式

Posted on 2016-06-22

刚看了一遍博客园原文讲三大范式(关系型数据库),是我觉看到目前最通俗的版本
参考于余晟:从范式谈起.

第一范式:属性不能拆分

换句话说,表中间的任何列都应当是承载信息的最小单位,不容许有更小的单位。一个人有身高、体重、性别等等,那么身高、体重、性别都应该对应专门的列,而不能取个名为“基本信息”的列,把这些信息统统塞进去。即数据库表的每一列都是不可分割的原子数据项。这个应该比较好理解,方便数据的索引与去重。

第二范式:主键必须最小

主键是这样的属性:对某个关系中所有n元组来说,主键必须是没有重复的,所以依靠它可以唯一定位某个n元组。主键可以是一个属性,也可以是多个属性。如果用列和表的说法,就是“唯一定位表中某行所要用到的列”。

  假设有一个电商卖家对接到电商平台,用表来存储订单信息,如果所有订单都来自同一个平台,可以用“平台订单号”作为主键;如果来自不同平台,各平台的订单号可能会重复,所以可以用“平台+订单号”作为主键……以此类推。

  第 2 范式的要求是:在满足第 1 范式的基础上,所有非主属性(主键之外的属性)必须完全依赖主键,而不能只依赖主键的某个子集。

alt text
上面的表不符合第二范式,主键是“平台+订单号”,这样才能区分金额,但是“对接人邮箱”只与“平台”有关,而“平台”是“平台+订单号”的子集。
  我们经常看到数据库的表会有一个毫无业务意义的自增字段作为主键,这样就保证了第二范式,因为主键只有一个属性,不存在真子集。同时,应当把非主属性和原来它依赖的“主键的子集”单独拿出来建表,比如建立一张“平台+对接人邮箱”的表格。

该范式是规定以最小的主键索引到某行数据

第三范式:主键必须直接依赖

 要满足第 2 范式,首先必须满足第 1 范式。同样的道理,要满足第 3 范式,首先也必须满足第 2 范式,并符合以下要求:所有非主属性对主键的依赖应当是直接的,不容许是间接的。也就是说,所有非主属性不容许依赖主键之外的属性。

alt text

上面的表不符合第三范式。主键是“平台+冠军种类”,但属性“品牌联系人邮箱”依赖于主键之外的属性“品牌”,虽然“品牌”依赖于表的主键,但“品牌联系人邮箱”对主键依赖是传递的。

  要让表符合第 3 范式,可以解除传递依赖,把对应的属性拆分出来单独创建表,比如把“品牌”和“品牌联系人邮箱”单独创建表。
alt text

Summary

三大范式核心观点就是去除冗余数据

1…678
zhong-wei

zhong-wei

23 posts
3 categories
7 tags
RSS
© 2016 - 2019 zhong-wei