分享
 
 
 

Refactoring to Patterns : Extract Creation Class

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Extract Creation Class

提取创建类

撰文/Joshua Kerievsky 编译/透明

一个类中有太多的创建方法,以至于无法从代码中看清这个类主要的责任。

将一组相互关联的类中的创建方法搬到一个创建类中去。

动机

从根上来说,这个重构其实就是Extract Class[Fowler],只不过是对类的创建方法进行的。一个类中存在创建方法,这很正常;但是随着创建方法越来越多,类本身的主要责任——它存在的主要目的——可能就变得越来越模糊,甚至被对象创建的逻辑给遮蔽住了。如果情况真是这样,就应该对这个类做一些调整,将创建方法移动到一个专门的创建类(Creation Class)中去,还这个类以本来面目。

创建类和抽象工厂(Abstract Factory)[GoF]都可以用来创建一族中的任意一种对象,从这一点来说,它们很相似。但是,它们之间的差异也很大,如下表所示:

创建类

抽象工厂

运行时可替换

可以实例化一族产品

容易支持新产品

接口与实现分离

可能

使用静态(static)方法实现

通常是

作为单件(Singleton)实现

经常是

一般来说,如果你希望只用一个类来创建对象,那么创建类会比较合适,因为不必在运行时更换对象,直接用创建类的静态方法来创建即可。尽管创建类和抽象工厂都经常用于创建一组相关的对象,但是这两者之间有一个最大的不同之处:你不会在运行时更换创建类,因为你不需要改变产品对象的家族。创建类通常被实现为一个包含静态方法的类,每个静态方法生成并返回一个对象实例。

沟通

重复

简化

当对象的创建在一个类的公开接口中占据了一大半的时候,这个类就已经不能很好地表述自己的主要用途了。创建一个特定的类专门用于创建对象实例,这样两个类都可以更好地表达自己的用途,更好地与使用者沟通。

在这个重构中,重复不是问题。

当创建对象的责任过多地与这个类的主要责任搅在一起的时候,这个类就无法简单。将创建代码提取到一个独立的创建类中,这样可以简化这个类。

过程

1. 识别出创建方法泛滥的那个类(我们把它叫做“A”)。

2. 新定义一个类,作为你的创建类。它的作用是从一组相关的类中创建不同的对象,根据其具体作用给它命名。

3. 将A类中所有的创建方法都移到这个新的类中来,设置好所有的访问控制。

4. 修改所有获取新对象的调用者,让它们从新的创建类那里获取对象。

范例

虽然我使用的范例代码跟Martin Fowler的不同,但是由于我天生懒惰,所以我还是想反复使用前面的例子。那么,如果你不介意的话,我们还是来看这个傻傻的Loan的例子吧,上面的代码草图画的就是这个例子。请假想下面的范例代码是有相应的测试代码的——我没有在正文中把测试代码写出来,因为这个重构非常简单。

1、我们的Loan类有许多代码都是负责创建Loan对象的:

public class Loan {

private double notional;

private double outstanding;

private int rating;

private Date start;

private CapitalStrategy capitalStrategy;

private Date expiry;

private Date maturity;

// . . . more instances variables not shown

protected Loan(double notional, Date start, Date expiry,

Date maturity, int riskRating, CapitalStrategy strategy) {

this.notional = notional;

this.start = start;

this.expiry = expiry;

this.maturity = maturity;

this.rating = riskRating;

this.capitalStrategy = strategy;

}

public double calcCapital() {

return capitalStrategy.calc(this);

}

public void setOutstanding(double newOutstanding) {

outstanding = newOutstanding;

}

// ... more methods for dealing with the primary responsibilities of a Loan, not shown

public static Loan newAdvisor(double notional, Date start, Date maturity, int rating)

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newLetterOfCredit(double notional, Date start,

Date maturity, int rating) {

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newRCTL(double notional, Date start,

Date expiry, Date maturity, int rating) {

return new Loan(notional, start, expiry, maturity, rating, new RCTLCapital());

}

public static Loan newRevolver(double notional, Date start,

Date expiry, int rating) {

return new Loan(notional, start, expiry, null, rating, new RevolverCapital());

}

public static Loan newSPLC(double notional, Date start,

Date maturity, int rating) {

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newTermLoan(double notional, Date start,

Date maturity, int rating) {

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newVariableLoan(double notional, Date start,

Date expiry, Date maturity, int rating) {

return new Loan(notional, start, expiry, maturity, rating, new RCTLCapital());

}

}

2、创建一个名叫LoanCreator的类。之所以起这样的名字,是因为它唯一的作用就是给客户提供一个可以获取Loan实例的地方:

public class LoanCreator {

}

3. Now I move all of the Creation Methods from Loan to LoanCreator, placing LoanCreator in the same package as Loan (and it’s Capital stategies) so it has the protection level it needs to instantiate Loans:

3、现在,将Loan类中所有的创建方法都移动到LoanCreator中,把LoanCreator和Loan类放在同一个包中,这样它就可以有足够的访问权限来访问Loan类的构造子、实例化Loan对象了。

public class LoanCreator {

public static Loan newAdvisor(double notional, Date start,

Date maturity, int rating)

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newLetterOfCredit(double notional, Date start,

Date maturity, int rating) {

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newRCTL(double notional, Date start,

Date expiry, Date maturity, int rating) {

return new Loan(notional, start, expiry, maturity, rating, new RCTLCapital());

}

public static Loan newRevolver(double notional, Date start,

Date expiry, int rating) {

return new Loan(notional, start, expiry, null, rating, new RevolverCapital());

}

public static Loan newSPLC(double notional, Date start,

Date maturity, int rating) {

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newTermLoan(double notional, Date start,

Date maturity, int rating) {

return new Loan(notional, start, null, maturity, rating, new TermLoanCapital());

}

public static Loan newVariableLoan(double notional, Date start,

Date expiry, Date maturity, int rating) {

return new Loan(notional, start, expiry, maturity, rating, new RCTLCapital());

}

}

4、最后,简单地修改一下调用的格式,重构就完成了。把

Loan termLoan = Loan.newTermLoan(…)

改成

Loan termLoan = LoanCreator.newTermLoan(…)

参考资料

[Fowler] Martin Fowler, etc., Refactoring, Addison-Wesley, 1999.

[GoF] Eric Gamma, etc., Design Patterns, Addison-Wesley, 1995.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有