interface Fruit{
public void eat();
}
class Apple implements Fruit{
public void eat(){
System.out.println("*** eat apple");
}
}
class Banana implements Fruit{
public void eat(){
System.out.println("*** eat banana");
}
}
public class TestDemo{
public static void main(String[] args)/*模拟客户端运行*/
{
Friut f = new Apple();
f.eat();
/*以下是新增加客户需求Banana的增加的代码*/
Friut g = new Banana();
g.eat();
/*由于一个接口可能有多个子类,即客户端的需求可能有多种,但是以上的设计模式,如果客户端发出了吃香蕉的请求,则
需要在客户端中修改(或增加代码),但是如果客户端的需求有上千成万种,此时修改代码就很不方便了。
在整个代码过程中,对客户端的最终工作是调用接口的虚函数,即获得一个接口Fruit对象f而后进行函数调用;
至于是被谁实例化的,客户端并不需要知道。而以上代码中最大的问题在于关键字new,使得程序的耦合度太高。
直接导致了客户端需求一大,代码就会不方便维护*/
}
}
我们知道,确认一个代码是否真的好的标准是:
1.客户端调用简单,不需要关注具体的细节;2.客户端之外的代码修改,不会影响用户的使用。
那么,可不可以让客户端只是输入一段字符串就好呢?
上面说到,接口对象是被谁实例化的客户端并不需要关心。所以我们增加一个过渡类Factory来实例化,使用(Fruit)作为函数声明的返回值,使用(new 接口Fruit的子类名)作为函数体内部的返回值;
然后,我们在客户端中修改客户端的调用方式,然客户输入的字符串作为实参传入过渡类的函数形参,由于函数由static修饰,所以应该使用过渡类名来调用。然后用Fruit接口对象来接收返回值。
由函数可知,该返回值就直接决定了new哪个接口的子类的对象了。所以使用接口对象f来调用eat()就可以。
如果客户输入了不同的字符串,就可以直接新增类。并在过渡类中进行条件的增加即可,main函数完全不用修改代码。
这样,代码维护起来就更加方便了。
下面给出修改后的代码:
interface Fruit{
public void eat();
}
class Apple implements Fruit{
public void eat(){
System.out.println("*** eat apple");
}
}
class Banana implements Fruit{
public void eat(){
System.out.println("*** eat banana");
}
}
class Factory{
public static Fruit getInstance(String className)/*声明为static表明这个类中不打算使用属性,参数className是客户输入的*/
{
if("apple".equals(className))
return new Apple();
else if("orange".equals(className))
return new Orange();
else return null;
}
}
public class TestDemo{
public static void main(String[] args)/*模拟客户端运行*/
{
Fruit f = Factory.getInstance("apple");
f.eat();
}
}