设计模式学习-桥接模式(Bridge)

意图 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 别名 Handle/Body 结构 参与者 Abstraction — 定义抽象类的接口。 — 维护一个指向Implementor类型对象的指针。 RefinedAbstraction — 扩充由Abstraction定义的接口。 Implementor — 定义实现类的接口,该接口不一定要与Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。 ConcreteImplementor — 实现Implementor接口并定义它的具体实现。 示例代码: public abstract class Abstraction { private Implementor impl; public Implementor getImpl() { return impl; } public void setImpl(Implementor impl) { this.impl = impl; } public Abstraction(Implementor impl) { this.impl = impl; } public abstract void operation(); } public class RefinedAbstraction extends Abstraction { public RefinedAbstraction(Implementor impl) { super(impl); } @Override public void operation() { getImpl()....

July 31, 2013

设计模式学习-适配器(Adapter)

如果你知道电源适配器的作用,就应该很容易理解这个模式。 意图: 将一个类的接口转换成客户希望的另外一个接口。 Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 别名: 包装器 Wrapper 结构: 类适配器 对象适配器 适用: 以下情况使用Adapter模式 你想使用一个已经存在的类,而它的接口不符合你的需求。 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。 (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。 双向适配器: 一般适配器对使用target接口的透明,无法给使用adaptee接口的使用。双向适配器可以解决这个问题,使适配器更透明。 相关模式: 模式Bridge的结构与对象适配器类似,但是Bridge模式的出发点不同:Bridge目的是将接口部分和实现部分分离,从而对它们可以较为容易也相对独立的加以改变。而Adapter则意味着改变一个已有对象的接口。 Decorator模式增强了其他对象的功能而同时又不改变它的接口。因此Decorator对应用程序的透明性比适配器要好。结果是Decorator支持递归组合,而纯粹使用适配器是不可能实现这一点的。 模式Proxy在不改变它的接口的条件下,为另一个对象定义了一个代理。

July 31, 2013

设计模式学习-创建型模式

用于创建对象的模式。包括单件模式(Singleton)、抽象工厂模式(Abstract Factory)、生成器模式(Builder)、工厂方法模式(Factory Method)、原型模式(Prototype)。 用一个系统创建的那些对象的类对系统进行参数化有两种常用方法: 一、生成创建对象的类的子类;这对应于使用 Factory Method模式。这种方法的主要缺点是,仅为了改变产品类,就可能需要创建一个新的子类。这样的改变可能是级联的。 二、对系统进行参数化的方法更多的依赖于对象复合:定义一个对象负责明确产品对象的类,并将它作为该系统的参数。这是 Abstract Factory、Builder和Prototype模式的关键特征。所有这三个模式都涉及到创建一个新的负责创建产品对象的“工厂对象”。Abstract Factory由这个工厂对象产生多个类的对象。 Builder由这个工厂对象使用一个相对复杂的协议,逐步创建一个复杂产品。 Prototype由该工厂对象通过拷贝原型对象来创建产品对象。 如何选择: 使用Abstract Factory、Prototype或Builder的设计甚至比使用Factory Method的那些设计更灵活,但它们也更加复杂。通常,设计以使用 Factory Method开始,并且当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化。 当然没必要就不要用。

July 31, 2013

设计模式学习-单件(Singleton)

意图: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 结构图: 代码示例: public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } public void test() { System.out.println("Singleton test"); } public static void main(String[] args) { Singleton s = Singleton.getInstance(); s.test(); } } 效果: 因为Singleton类封装它的唯一实例,所以它可以严格的控制。 注意: Singleton不是说只能唯一,也可以控制其实例的数量,对多个实例的创建和控制。 Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。 实现: 保证一个唯一的实例是该模式的重点,不同语言对此有不同的方法。面对语言特性,还需要注意并发同步等问题。 相关模式: Abstract Factory、Builder、Prototype都可以用Singleton实现。

July 31, 2013

设计模式学习-原型(Prototype)

很少见到,我都没遇到过,或是遇到过也没注意。 意图: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 结构: Prototype ——声明一个克隆自身的接口 ConcretePrototype ——实现一个克隆自身的操作 示例代码: public abstract class Prototype implements Cloneable { public Prototype clone() { try { return (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } public abstract String getThing(); } public class ConcretePrototype extends Prototype { @Override public String getThing() { return "ConcretePrototype"; } } public class Client { public static void main(String[] args) { ConcretePrototype cp = new ConcretePrototype(); ConcretePrototype newCp = (ConcretePrototype) cp....

July 30, 2013

设计模式学习-工厂方法(Factory Method)

意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method使一个类的实例化延迟到其子类。 别名: 虚构造器(Virtual Constructor) 结构: Product — 定义工厂方法所创建的对象的接口。 ConcreteProduct — 实现Productt接口。 Creator — 声明工厂方法,该方法返回一个 Product类型的对象。Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的 ConcreteProduct对象。 ConcreteProduct对象 — 可以调用工厂方法以创建一个Product对象。 ConcreteCreator — 重定义工厂方法以返回一个ConcreteProduct实例。 代码示例: Creator类 public abstract class Creator { protected abstract Product factoryMethod(); public void anOperation() { Product product = factoryMethod(); //do some thing } } ConcreteCreator类 public class ConcreteCreator extends Creator { @Override protected Product factoryMethod() { return new ConcreteProduct(); } } 问题: 可能仅为了创建适当的 Product对象而迫使你创建Creator子类。 适用性: 一个系统要独立于它的产品的创建、组合和表示时。 一个系统要由多个产品系列中的一个来配置时。 当你要强调一系列相关的产品对象的设计以便进行联合使用时。 当你提供一个产品类库,而只想显示它们的接口而不是实现时。 相关模式: Abstract Factory经常用工厂方法来实现; 工厂方法通常在Template Method中被调用; Prototype不需要创建Creator的子类。但是,它们通常要求一个针对Product类的Initialize操作。Creator使用Initialize来初始化对象。而Factory Method不需要这样的操作。

July 30, 2013

设计模式学习-生成器(Builder)

用来构建复杂的实例,java的StringBuilder就是一个Builder模式的例子。 意图: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 结构: 代码示例: Builder类 public abstract class Builder { protected String product; public Builder() { product = new String(""); } public void buildPart(String part) { //默认空实现 } public String getResult() { return product; } } ConcreteBuilder类 public class ConcreteBuilder extends Builder { @Override public void buildPart(String part) { product += part; } } Director类 public class Director { private Builder builder; public Director(Builder builder) { this.builder = builder; } public void Construct() { for (int i = 0; i < 10; i++) { builder....

July 30, 2013

设计模式学习-抽象工厂(Abstract Factory)

意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类 。 别名: Kit 结构: 代码示例: AbstractFactory类 public abstract class AbstractFactory { public abstract AbstractProductA createProductA(); public abstract AbstractProductB createProductB(); } ConcreteFactory类 public class ConcreteFactory1 extends AbstractFactory { @Override public AbstractProductA createProductA() { return new ProductA1(); } @Override public AbstractProductB createProductB() { return new ProductB1(); } } public class ConcreteFactory2 extends AbstractFactory { @Override public AbstractProductA createProductA() { return new ProductA2(); } @Override public AbstractProductB createProductB() { return new ProductB2(); } } AbstractProduct类...

July 29, 2013

《重构》学习笔记-构筑测试系统与大型重构

构筑测试系统 测试……一年前,我开发的时候还是很不在乎测试,不过那个时候也没人告诉我测试的重要性。直到意识到要提高自己,学习中看到了那么多提到测试的,所以慢慢的尝试使用(大部分是单元测试),然后深深的爱上了单元测试(其他测试呢,好吧,编程中的确比较少用到其他测试,我比较懒)。 作者在前面反复提到测试在重构中的重要性,这章就是介绍测试的。 自我测试代码的价值: 编码往往只占了开发中的小部分时间,很多时间不是在沟通、设计,就是在找 BUG 。。。专业点,应该叫调试( debug )。测试的主要作用就是帮助调试,帮助开发中发现潜在的 BUG ,这样我们就可以少话点时间在调试上了。频繁进行测试是极限编程(下一个学习的内容)的重要一环。 确保所有测试都是自动化,让它们检查自己的测试结果。 一整组测试就是一个强大的 BUG 侦测器,能够大大缩减查找 BUG 所需要的时间。 JUNIT : 看来 JUNIT 的历史很悠久啊,作者写书的时候就已经很成熟了。我想这个不需要多说了,现在有关 JUNIT 的介绍到处都是。我也喜欢用 JUNIT ,不过看书中的介绍的 JUNIT 的基本使用有点老了,完全忽略吧。 重构前先为需要重构的功能构建好测试用列,在重构中,每次变动都需要进行测试,以确保重构没有给程序带来什么BUG。这个很重要。 大型重构 大型重构的重要性:大型重构没有那些小动作那样立竿见影的效果,不过它可以帮助我们解决那些堆积了很久,影响范围又很大的问题。 Tease Apart Inheritance (梳理并分解继承体系) 用于处理混乱的继承体系——这种继承体系往往以一种令人迷惑的方式组合了数个不同方面的变化( variations )。 某个继承体系( inheritance hierarchy )同时承担两项责任。 建立两个继承体系,并通过委托关系( delegation )让其中一个可以调用另一个。 Convert Procedural Design to Object (将过程化设计转化为对象设计) 可以帮助你解决一个「古典」问题:如何处理程序性代码( procedural code )? 你手上有一些代码,以传统的过程化风格( procedural style )写就。 将数据记录( data records )变成对象,将行为分开,并将行为移入相关对象之中。 Separate Domain from Presentation (将领域和表述 / 显示分离) 将业务逻辑( business logic )与用户界面( user interface )隔离开来。...

July 29, 2013

《重构》学习笔记-代码的坏味道

代码的坏味道 … 老外没有艺术细胞,作为一名大师级人物,好歹给起个好听点的名称。向金庸老人家学习下,让我们也感染下艺术气息。 我认为吗,坏味道就是对一段问题代码的感觉,从感性慢慢分析到理性。这种感觉需要在实践中培养。观看这里的介绍只能有个大概的理解方向,只有在反复在实际的代码中去体会,才能运用自如。 我也是爱国人士,也很不喜欢英语,不过毕竟都是老外的东西,为了避免一些名词的混淆,我还是用英语加翻译的方式。 一、 重复代码( Duplicated Code ) 很直观的一个问题,就算新手也很快能看出。如果是同一个类里面有重复代码,使用 Extract Method (提炼函数)把重复的给提取出来;如果重复代码分别在一个类的两个子类中,则先提取代码,然后使用 Pull Up Method (函数上移)把提取的函数放到 superclass 中;如果在好不相干的两个类中,则考虑使用 Extract Class (提炼类)把重复代码独立成一个类,也可以把函数放在其中一个类中,另一个应用这个之,看实际情况了。 二、 过长函数( Long Method ) 看 50 行的 20 个函数比看一千行的一个函数强多了,所以么函数不宜过长,或者说就应该短, java 在调用函数时候的开销很小,一般不会产生性能问题。我也讨厌那些长函数,看到后面逻辑都乱了,本人见过两千行的函数,唉,一半注解一半代码。 99% 的场合只需要使用 Extract Method (提炼函数)。如果函数内有大量的参数和临时变量,可以尝试 Extract Method (提炼函数)把那些参数和临时变量当作参数,运用 Replace Temp With Query (以查询取代临时变量)来消除暂时元素。 Introduce Parameter Object (引入参数对象)和 Preserve Whole Object (保持对象完整)则可以把过长的参数变简洁。如果做完上述发现还是有太多参数和变量,可以使用杀手锏: Replace Method With Method Object (以函数对象取代函数)。条件和循环常常是提取的信号,可以使用 Decompose Conditional (分解条件式)来处理条件式。循环则可以提炼一个独立的函数。 三、 过长类( Large Class ) 这种可以使用 Extract Class (提炼类)提炼出内容有相关性的。如果类里面有数个变量有着一样的前缀或后缀,用 Extract Subclass (提炼子类)会比较简单。如果是 GUI 类,可以把数据和行为移到单独的 domain 对象中去,运用 Duplicate Observed Data (复制被监视数据)同步数据。...

July 29, 2013