多态(Polymorphism)
面向对象的三大特性:封装Encapsulation(getter,setter)和继承Inheritance(extend, override, overwrite)很容易理解,但多态(Polymorphism)比较难理解,难不在形式,而是它的用处在哪里。下面举个例:
class Wine { //定义一个父类
void whatisit(){
System.out.println("This is Wine");
}
}
class RedWine extends Wine { //定义一个Wine的子类RedWine
void whatisit(){
System.out.println("This is RedWine");
}
}
class Beer extends Wine { //定义一个Wine的子类Beer
void whatisit(){
System.out.println("This is Beer");
}
}
class Waiter{//定义Wait类的serve方法时的形参是父类Wine,而不需具体的子类,解耦合,增加灵活性
static void serve(Wine wine){
wine.whatisit();
}
}
public class Guest{
public static void main(String[] args){
Wine wine = new RedWine(); //用父类引用,指向子类对象,实现具体的逻辑
new Waiter().serve(wine);
}
}
抽象类Abstract class和接口Interface
abstract class表示的是"is a"关系,模板父类;interface表示的是"like a"关系,交互的规范。
接口只能定义静态常量,抽象方法,不包含初始化块和构造函数;抽象类可以有普通变量,不普通方法,可以包含初始化和构造函数。
接口可以实现多个接口;抽象类只能有一个父类。
例子:
那么具有报警功能的Door的定义方式如下:
解决方案一:
abstract class Door {
abstract void open();
abstract void close();
abstract void alarm();
}
或者
interface Door {
void open();
void close();
void alarm();
}
解决方案二:
既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:
1.这两个概念都使用abstract class方式定义;
2.两个概念都使用interface方式定义;3.
3.一个概念使用abstract class方式定义,另一个概念使用interface方式定义。
显然,由于Java语言不支持多重继承,所以(方法1)两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。
如果(方法2)两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用interface方式定义)反映不出上述含义。
interface Door {
void open();
void close();
}
interface Alarm {
void alarm();
}
class AlarmDoor implements Door, Alarm {
void open() { … }
void close() { … }
void alarm() { … }
}
如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示(方法3):
abstract class Door {
abstract void open();
abstract void close();
}
interface Alarm {
void alarm();
}
class AlarmDoor extends Door implements Alarm {
void open() { … }
void close() { … }
void alarm() { … }
}
这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。
设计模式Design pattern
简单工厂Simple Factory- 通过调用方法来创建对象实例
public interface Car {
public void drive();
}
public class Benz implements Car{
public void drive() {
System.out.println("Driving Benz ");
}
}
public class Bmw implements Car{
public void drive() {
System.out.println("Driving Bmw ");
}
}
public class Driver{
//static method
public static Car driverCar(String s)throws Exception {
//create concrete class
if(s.equalsIgnoreCase("Benz"))
return new Benz();
else if(s.equalsIgnoreCase("Bmw"))
return newBmw();
else throw new Exception();
}
}
public class Magnate {
public static void main(String[] args){
try{
//create the benz car instance by invoking the Class Driver's drive method
Car car = Driver.driverCar("benz");
car.drive();
} catch(Exception ex){
ex.printStackTrace();
}
}
}
单例Singleton--Protected/private 构造函数保证只有一个实例,通过调用方法创造对象实例
public class Singleton2 {
private static Singleton2 instance = null;
//
private Singleton2(){
}
public static synchronized Singleton2 getInstance() {
if (instance==null)
instance=new Singleton2();
return instance;
}
}
public class Singleton3
{
private static HashMap sinRegistry = new HashMap();
static private Singleton3 s = new Singleton3();
//构造函数protected, 不能new object(), 保证只有一个实例
protected Singleton3()
{}
public static Singleton3 getInstance(String name)
{
if(name == null)
name = "Singleton3";
if(sinRegistry.get(name)==null)
{
try{
sinRegistry.put(name , Class.forName(name).newInstance());
}catch(Exception e)
{
e.printStackTrace();
}
}
return (Singleton3)(sinRegistry.get(name));
}
public void test()
{
System.out.println("getclasssuccess!");
}
}
Quick way for coding
1.Properties class to read ini file
2. Arraylist and hashmap: Iterator.next()/Iterator.hasNext or for (String str : Arraylist) {}