全部博文(164)
分类: 系统运维
2012-05-07 15:35:23
今天上午做了设计模式的培训。以前自以为看懂了一些模式的东西,现在觉得还是有很多的东西没有理解到。每次说起一种模式有多少种分类时,常常会被人笑话又问茴香豆的茴字有几种写法。但是,我觉得不是的,只有当你能够深刻理解你为什么要那样做,那样做有什么好处的时候,你才算真正的明白了设计模式。
今天开会的时候,还说到一个话题,就是设计模式有几个基本的原则,这些原则是设计模式产生的根本原因。我觉得说的对,稍后我会把那些内容补上。
这次我们学习了好几个模式,我个人认为有几个模式我并没有参透,所以暂时写写我理解了的一两个吧!首先是简单工厂模式。 这个模式说起来很简单,使用一个类,类里包含一个方法,该方法根据传递进来的参数决定返回的类实例。 以前,我以为随便想要什么类,传个参数进去,然后把类实例返回就好了。现在想想很傻。因为我忽略了返回值类型啊!所以简单工厂中,方法的返回类型限制,要求创建出来的类必须实现了共同的接口,或继承了共同的父类。
使用简单工厂的原因:
下面举个实在的例子: 假设你有一个院子,院子里中了很多水果,苹果,草莓和葡萄。有一个园丁在管理他们,如果需要的时候就去园丁那里获取。
如果按照普通的定义,我们会定义苹果,草莓和葡萄,园丁几个类,需要哪个用哪个。
这样做有什么问题呢?如果有一天我希望原来的苹果全部换成草莓,怎么办?一个个的替换掉吗?显然不好啊!!如果我们使用简单工厂模式,直接改变方法返回的值就ok了!
所以,原因一:替换简单,程序的灵活性更强。
除此之外,如果我们新增了一个水果类,比如香蕉,我们不必在别的地方处理,只需在工厂中增加一个判断就可以了。
所以,原因二:扩展方便,快捷。
如何实现简单工厂:
1.共有的接口
public interface Fruit {
void grow();
void harvest();
void plant();
}
2.各个具体实现类:
//苹果
public class Apple implements Fruit{
private int treeAge;
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
public int getTreeAge() {
return treeAge;
}
/**
* grow
*/
public void grow() {
System.out.println("Apple is growing...");
}
/**
* harvest
*/
public void harvest() {
System.out.println("apple had harvested");
}
/**
* plant
*/
public void plant() {
System.out.println("apple had planted");
}
}
//葡萄
public class Grape implements Fruit{
private boolean seedless;
public boolean getSeedless()
{
return seedless;
}
public void setSeedless()
{
this.seedless = seedless;
}
public Grape() {
}
/**
* grow
*/
public void grow() {
System.out.println("Grape is growing");
}
/**
* harvest
*/
public void harvest() {
System.out.println("grape is havest");
}
/**
* plant
*/
public void plant() {
System.out.println("grape is planted");
}
}
3.园丁工厂:
public class FruitGardener {
public static Fruit factory(String which) throws Exception
{
if(which.equals("apple"))
{
return new Apple();
}else if(which.equalsIgnoreCase("Grape"))
{
return new Grape();
}
else
{
throw new Exception("no this fruit!");
}
}
}
简单工厂模式的扩展:
前面的设计虽然扩展起来是很容易的,但是还是有些问题,就是每次添加类的时候需要到工厂中增加一个处理。如果你不希望那样,怎么办呢?下面的代码就解决了这个问题了。
public class FruitGardener {
public static Fruit factory(String which) throws Exception
{
return (Fruit)Class.forName(which).newInstance();
}
}
但是这个方法还存在以下的缺点:
1.有时候仅仅newInstance()不一定足够,比如创建苹果的例子,还要带一个颜色参数,
当然还有更复杂的例子,如创建一个jndi对象,如从池里取对象等等。
2.有时候不是简单的传入一个className,还需要对传入的参数作分析以创建不通的对象, 如jdbc根据不同的连接串创建不同的Connection。再比如,如果使用苹果的地方都需要换成葡萄只需要将switch语句对应苹果的一句换成葡萄类的实例就好。但是用上面的方法就不可取了。
简单工厂的缺点
上面我们谈了简单工厂的优点和扩展。下面我们来看看简单工厂的缺点。有一个被认为最不好的缺点,就是不符合OCP原则。也就是说,当你增加一个新类时,你必须修改工厂方法,添加一段处理代码。这不符合,已有代码尽可能不改变的原则。于是工厂方法模式应运而生了。