Java与模式(一)
探讨设计模式基于Java语言的实现以及Java中一些易混淆的概念
面向对象的设计原则:
-------------------------------------- 一个Java接口的方法只能是抽象的和公开的,比Java抽象类更为抽象化,Java接口不能有构造函数。Java接口可以有public、静态的和final的属性。接口与类的最重要区别是,接口仅仅描述方法的特征(Signature),而不给出方法的实现;而类不仅给出方法的特征,而且给出方法的实现。 标识接口是没有任何方法和属性的接口。标识接口不对实现它的类有任何语义上的要求,它仅仅表明实现它的类属于一个特定的类型。如java.io.Serializable和java.rmi.Remote都是标识接口。 package java.io; public interface Serializable {} package java.rmi; public interface Remote{} 常量接口是指用Java接口来声明一些常量,然后由实现这个接口的类使用这些常量。 抽象类仅提供一个类型的部分实现。抽象类可以有实例变量,以及一个或者多个构造函数。抽象类可以同时有抽象方法和具体方法。一个抽象类不会有实例,这些构造函数不能被客户端调用来创建实例。一个抽象类的构造函数可以被其子类调用,从而使一个抽象类的所有子类都可以有一些共同的实现,而不同的子类可以在此基础上有其自己的实现。Java抽象类与Java接口一样,都用来声明一个新的类型,并且作为一个类型的等级结构的起点。但是,Java接口具有比Java抽象类更好的特性,因此,应当优先使用Java接口声明一个超类型。抽象类一定是用来继承的。Scott Meyers曾经指出,只要有可能,不要从具体类继承。在一个从抽象类到多个具体类的继承关系中,共同的代码应当尽量移动到抽象类里。而数据尽量移动到具体类中。 -------------------------------------- 什么时候才应当使用继承复用? Peter Coad认为,继承代表"一般化/特殊化"关系,其中基类代表一般,而衍生类代表特殊,衍生类将基类特殊化或者扩展化。只有当以下的Coad条件全部被满足时,才应当使用继承关系: (1)子类是超类的一个特殊种类,而不是超类的一个角色,也就是要区分"Has-A"与"Is-A"两种关系的不同。Has-A关系应当使用聚合关系描述,而只有Is-A关系才符合继承关系。 (2)永远不会出现需要将子类换成另一个类的子类的情况。如果设计师不是很肯定一个类会不会在将来变成另一个类的子类的话,就不应当将这个类设计成当前这个超类的子类。 (3)子类具有扩展超类的责任,而不是具有置换掉(Override)或者注销掉(Nullify)超类的责任。如果子类需要大量的置换掉超类的行为,那么这个子类不应当成为这个超类的子类。 (4)只有在分类学角度上有意义时,才可以使用继承,不要从工具类继承。 -------------------------------------- 在面向对象领域中,两个类之间可以发生的三种不同的耦合关系: (1)零耦合(Nil Coupling)关系:如果两个类没有耦合关系,就称之为零耦合。 (2)具体耦合(Concrete Coupling)关系:具体性耦合发生在两个具体的(可实例化)类之间,经由一个类对另一个具体类的直接引用造成。 (3)抽象耦合(Abstract Coupling)关系:抽象耦合关系发生在一个具体类和一个抽象类(或者Java接口)之间,使两个必须发生关系的类之间存在最大的灵活性。 -------------------------------------- 变量被声明时的类型叫做变量的静态类型(Static Type),有些称之为明显类型(Apparent Type),变量所引用的对象的真实类型叫做变量的实际类型(Actual Type)。如 List employees = new Vector(); employees变量的静态类型是List,而它的实际类型是Vector。 -------------------------------------- Java接口与Java抽象类的区别: (1)这两者最明显的区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口则不可以。这大概是Java抽象类的唯一优点。如果向一个抽象类加入一个新的具体方法,那么所有的子类型就都得到了这个新的具体方法,而Java接口则做不到这一点。如果向一个Java接口加入一个新的方法的话,所有实现这个接口的类就不能全部成功地通过编译了,因为它们没有实现这个新声明的方法。这是Java接口的一个缺点。 (2)一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于Java语言限制一个类只能从最多一个超类继承,因此将抽象类作为类型定义工具的效能大打折扣。而一个类却可以实现多个接口。 (3)从代码的重构的角度上讲,将一个单独的Java具体类重构成一个Java接口的实现是很容易的。只需要声明一个Java接口,并将重要的方法添加到接口声明中,然后在具体类定义语句后面加上一个合适的implements子句就可以了。而为一个已有的具体类添加一个Java抽象类作为抽象类型却不那么容易,因为这个具体类有可能已经有一个超类。这样一来,这个新定义的抽象类只要继续向上移动,变成这个超类的超类,如此循环,最后这个新定义的抽象类必定处于整个类型等级结构的最上端,从而使等级结构中的所有成员都会受到影响。 (4)Java接口是定义混合类型(Mixin Type)的理想工具。所谓混合类型,就是在一个类的主类型之外的次要类型。一个混合类型表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为。 -------------------------------------- 迪米特法则(LoD)的各种表述:
广义迪米特法则在类的设计上的体现:
-------------------------------------- 简单工厂模式(Simple Factory):是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。工厂模式有以下几种形态:
简单工厂模式的结构: public class Creator { public static Product factory() { return new ConcreteProduct(); } }
public interface Product{} public class ConcreteProduct implements Product { public ConcreteProduct(){} }
|
|