设计模式------工厂

      LK计划接下来的一段时间,来重点学习一下设计模式。当然LK不会把每种设计模式都讲一遍,经常使用到的设计模式才是LK要跟大家分享的重点。LK的设计模式学习之路,主要弄清楚以下几个问题:

  1.       这种模式是干啥的
  2.       这种模式怎么用
  3.        能解决什么问题
  4.        有什么应用场景
  5.        用它有什么优势

听着LK这样一说,我不禁开始有所感慨,这个问题让我想起了哲学的基本问题,你从哪里来,要到哪里去。中间过程只不过是短短数十载,留给你自己去体会。哈哈,又开始瞎扯淡了。

       那么LK为什么要学习设计模式呢?答案很简单,LK不想让自己写的代码如此的繁琐,if~else满屏幕飞,LK也想让自己的代码充满智慧的光芒。当然学习设计模式也有助于理解源码。体会开源大神的杰作。我们总是听人说读一本自己喜爱的书就好像是与作者在书中对话,我真的很羡慕这样的人,但是我好像从来没有过这样的体会。那我觉得设计模式就是程序的思想,大量的程序逐渐清晰的产生了现在我们熟知的设计模式。只有掌握这些你才能在程序的世界里和大神对话。

     来看看LK即将要说的工厂模式,提到工厂我们就会想到富士康。不仅是工厂还是跨国工厂。其实工厂模式和现实的工厂是一样的,不同的工厂生产不同的产品,同一个工厂也可以生产不同的产品。有点像多啦a梦的大口袋,要啥有啥。多啦A梦LK童年的会议。我们的工厂设计模式也是一样,由工厂产生所需要的对象,或者由大工厂产生小工厂,在由小工厂产生对象。万物皆对象,真实工厂造就万物,程序工厂造就所有对象。

   LK就以造汽车来和大家聊一聊工厂模式,很简单一间工厂,生产法拉利和劳斯莱斯。

 来看看类图

 

来看看具体实现 

接口生产的汽车

package factory;

public interface Car {
	//加油
	void oil();
}

实现类法拉利

/**
    * 具体产品---法拉利
 * @author yrz
 *
 */
public class Ferrari implements Car{

	public void oil() {
		System.out.println("法拉利-----正在加油");
	}

}

实现类劳斯莱斯

/**
  * 具体实现类劳斯莱斯
 * @author yrz
 *
 */
public class RollsRoyce implements Car{

	public void oil() {
		System.out.println("劳斯莱斯------正在加油");
	}

}

汽车生产工厂

/**
  * 汽车工厂用于生产具体汽车
 * @author yrz
 *
 */
public class CarFactory {
	
	
	public Car createCar(String carType) {
		if (carType == null) {
			return null;
		}
		if (carType.equalsIgnoreCase("Ferrari")) {
			return new Ferrari();
		} else if (carType.equalsIgnoreCase("RollsRoyce")) {
			return new RollsRoyce();
		}

		return null;
	}
}

测试类

public class FactoryPatternDemo {
	public static void main(String[] args) {
		CarFactory carFactory = new CarFactory();

		// 生产劳斯莱斯
		Car car1 = carFactory.createCar("RollsRoyce");

		car1.oil();

		// 生产法拉利

		Car car2 = carFactory.createCar("Ferrari");

		car2.oil();
	}
}

运行结果:

到此我们的法拉利和劳斯莱斯就造好了,加满油就可以上路了。

可以看到只要我们知道要生产什么类型的车,就可以由工厂去生产。

问题来了,我要生产车,就需要生产车的零件。而且一些特殊的零件还要去其它国家采购,而现在我们都是在用现有的零件直接组装。所以现有工厂就显然不够用了。

抽象工厂的概念就应用产生。LK理解的抽象工厂就是已有工厂的再次抽象,一种是大工厂下面的小工厂,另一种是前者工厂和后者工厂有很大的联系。

还是以生产汽车为例,这次LK添加了生产外壳,轮子,引擎的三个工厂。再由每个生产零件的子工厂生产法拉利和劳斯莱斯各自需要的零件。

来看看具体实现类

发动机接口

/**
   * 发动机
 * @author yrz
 *
 */
public interface Engine {
	void dosomething();
}

外壳接口

/**
  * 外壳
 * @author yrz
 *
 */
public interface Shell {
	void dosomething();
}

轮子接口

/**
   *  轮子
 * @author yrz
 *
 */
public interface Wheel {
	void dosomething();
}

抽象工厂类

/**
   * 总的组装工厂
 * @author yrz
 *
 */
public abstract class AbstractFactory {
	//组装所需-----引擎
	abstract Engine getEngine(String engine);
	//组装所需-----轮子
	abstract Wheel getWheel(String wheel);
	//组装所需----外壳
	abstract Shell getShell(String shell);

}

发动机工厂

/**
 * 引擎子工厂
 * 
 * @author yrz
 *
 */
public class EngineFactory extends AbstractFactory {

	@Override
	Engine getEngine(String engine) {
		if (engine == null) {
			return null;
		}

		if (engine.equalsIgnoreCase("FerraEngine")) {
			return new FerraEngine();
		} else if (engine.equalsIgnoreCase("RollsRoyceEngine")) {
			return new RollsRoyceEngine();
		}
		return null;
	}

	@Override
	Wheel getWheel(String wheel) {
		return null;
	}

	@Override
	Shell getShell(String shell) {
		return null;
	}

}

轮子工厂

/**
 * 轮子子工厂
 * @author yrz
 *
 */
public class WheelFactory extends AbstractFactory{

	@Override
	Engine getEngine(String engine) {
		return null;
	}

	@Override
	Wheel getWheel(String wheel) {
		if (wheel == null) {
			return null;
		}

		if (wheel.equalsIgnoreCase("FerraWheel")) {
			return new FerraWheel();
		} else if (wheel.equalsIgnoreCase("RollsRoyceWheel")) {
			return new RollsRoyceWheel();
		}
		return null;
	}

	@Override
	Shell getShell(String shell) {
		return null;
	}

}

外壳工厂

/**
 * 外壳子工厂
 * @author yrz
 *
 */
public class ShellFactory extends AbstractFactory{

	@Override
	Engine getEngine(String engine) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	Wheel getWheel(String wheel) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	Shell getShell(String shell) {
		if (shell == null) {
			return null;
		}

		if (shell.equalsIgnoreCase("FerraShell")) {
			return new FerraShell();
		} else if (shell.equalsIgnoreCase("RollsRoyceShell")) {
			return new RollsRoyceShell();
		}
		return null;
	}

}

工厂生产类

/**
 * 生产子工厂
 * 
 * @author yrz
 *
 */
public class FactoryProducer {
	static AbstractFactory getFactory(String factoryType) {
		if (factoryType == null) {
			return null;
		}
		if (factoryType.equalsIgnoreCase("Engine")) {
			return new EngineFactory();
		} else if (factoryType.equalsIgnoreCase("Wheel")) {
			return new WheelFactory();
		} else if (factoryType.equalsIgnoreCase("Shell")) {
			return new ShellFactory();
		}

		return null;
	}
}

测试类

public class AbstractFactoryPatternDemo {
	public static void main(String[] args) {
		// 获取引擎工厂
		AbstractFactory engineFactory = FactoryProducer.getFactory("Engine");
		// 获取具体引擎
		Engine feEngine = engineFactory.getEngine("FerraEngine");

		feEngine.dosomething();

		Engine roEngine = engineFactory.getEngine("RollsRoyceEngine");

		roEngine.dosomething();


		System.out.println("--------------------------");
		
		// 获取轮子工厂
		AbstractFactory wheelFactory = FactoryProducer.getFactory("Wheel");
		// 获取具体轮子
		Wheel feWheel = wheelFactory.getWheel("FerraWheel");

		feWheel.dosomething();

		Wheel roWheel = wheelFactory.getWheel("RollsRoyceWheel");

		roWheel.dosomething();

		System.out.println("--------------------------");
		
		// 获取外壳工厂
		AbstractFactory shellFactory = FactoryProducer.getFactory("Shell");
		// 获取具体外壳
		Shell feShell = shellFactory.getShell("FerraShell");

		feShell.dosomething();

		Shell roShell = shellFactory.getShell("RollsRoyceShell");

		roShell.dosomething();
	}
}

 

运行结果:

这里就省略了具体零件实现类,有兴趣可以根据我的类图和运行结果自己尝试。

是不是对工厂有了新的认识。

总结一下

 

写到这,LK前段时间写过spring IOC源码理解,可以看到BeanFactory中实际是一个hashmap,key存放着每一个创建的bean name。获取具体工厂时只需要bean的name即可,和我们要生产什么类型的零件输入零件名称,想要生产什么类型的car输入car的类型是一个道理。感兴趣可以去看看LK的那片文章。

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值