作者H45 (!H45)
看板java
标题Re: [问题] setXXX
时间Wed Oct 22 09:44:38 2008
※ 引述《hougzou (该换个重训方法了)》之铭言:
: ※ 引述《ChienHsiang (不务正业工程师)》之铭言:
: : 或许也可以把 Java Bean 的"习惯性用法"当成一种 Pattern 吧
: : 我觉得倒没什麽谁对谁错...
: : 何况很多以前大家认为错的,现在又是那麽的理所当然...
: : Pattern Refactory後,又是一种新的Pattern不是吗?
: 物件导向概念里头,有个大家都知道,却都常忽略的概念,就是「封装」。
: 这东西简单来说,就是类别中的变数,不能给其他类别直接存取,而必须
: 提供setter/getter来设定或取得「变数值」。
: (注意!直接操作变数与间接取值是完全不同的两回事)
: 这做法可以让类别设计者能保留程式内容的弹性,当需求有变时,只需更改
: 类别内部对变数操作的方法,不用让引用此类别的程式区段同时做修改。
: 至於为什麽要用setXXX以及getXXX。
: 如果某人的Java类别没有重复利用的价值,那麽setXXX/getXXX改为任何有效的
: 方法名称都可以。可是,如果这个类别有重复利用的可能,而且不知道会在
: 哪个领域用到,则采用getXXX/setXXX反而可以让这只类别提供Java Bean的功能。
: 不过之所以用set/get来当字首,简单来说就是短、简洁、易记。试想一下,
: 如果改用assignXXX/fetchXXX,是不是觉得很累缀哩?依学习以及使用的观点
: 来看用set/get的确是种行为正确的选择。
: 希望这些能解答讨论串原PO的疑惑。
最近在重构 (Refactoring) 的时候遇到需要把所有直接存取的叙述全部改成 Getter 和
Setter 的情境,我正把一棵类别大爆炸 (超庞大) 的继承树引入装饰者模式 (Decorator
Pattern),然而,若装饰者继承的元件含有可见的 (Visible, for instance: public,
protected) 成员变数,那麽装饰者无法引导呼叫端使用内部元件的变数,而被误用至装
饰者本身的变数。
举例而言:
/**
* 含有可见变数的元件
*/
public class Component {
// Oops! 可见的变数!!
public int properties;
// 复杂的计算会修改此物件的属性
public int complexMethod(int param) {
return param + (properties++);
}
}
/**
* 元件的装饰者
*/
public class Decorator extends Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
// 把计算委托给元件处理
public int complexMethod(int param) {
return component.complexMethod(param);
}
}
/**
* 错误的呼叫者
*/
public class Drive {
public static void main(String args[]) {
Component component = new Component();
Decorator decorator = new Decorator(component);
// 修改数值至装饰者,但应修改至元件才对,错误!
decorator.properties = -1;
// 因为上面给值没给到元件,所以这边回传的值不会反应到结果
int result = decorator.complexMethod(0);
// 期望 result 等於 -1, 但却等於 0
}
}
=========================================================================
「封装」是解决之道
=========================================================================
修改後的元件与装饰者:
/**
* 包装後的元件
*/
public class Component {
// 将此变数设为不可见 (private)
private int properties;
public int complexMethod(int param) {
return param + (properties++);
}
// Setter of properties
public void setProperties(int properties) {
this.properties = properties;
}
// Getter of properties
public int getProperties() {
return properties;
}
}
/**
* 元件的装饰者
*/
public class Decorator extends Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
public int complexMethod(int param) {
return component.complexMethod(param);
}
@Override
public int getProperties() {
// 委托元件将属性回传
return component.getProperties();
}
@Override
public void setProperties(int properties) {
// 设定属性至元件内
component.setProperties(properties);
}
}
/**
* 正确的呼叫者
*/
public class Drive {
public static void main(String args[]) {
Component component = new Component();
Decorator decorator = new Decorator(component);
// 透过 Setter 来设定元件的变数,正确!
decorator.setProperties(-1);
// 因为上面给值到元件,所以这边回传的值会反应到结果
int result = decorator.complexMethod(0);
// 期望 result 等於 -1, 确实地 result 正好等於 -1
}
}
引入装饰者模式至一棵继承树必须确保所有的成员变数都是不可见 (invisible, for
instance: private) 的,否则无法阻止呼叫者修改装饰者的变数,要达到所有的成员变
数都是不可见,请封装您的元件变数,拒绝外面任何的使用者修改。
因此,请没事就封装您的成员变数 XD (无误)
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.116.247.13