主要详解简单工厂模式到抽象工厂模式的演变。
简单工厂模式
即静态工厂模式
1.将对象的创建和使用分开;
2.将生产过程集中,便于集中管理;
3.当需要创建的对象类有变动时,就不用在所有new 的地方修改了,直接修改工厂类即可;
/**
* 简单工厂模式 --- 静态工厂模式
*/
public class StaticFactory {
public static final int TYPE_APPLE = 1;//苹果
public static final int TYPE_ORANGE = 2;//桔子
public static final int TYPE_BANANA = 3;//香蕉
public static Fruit getFruit(int type){
if(TYPE_APPLE == type){
return new Apple();
} else if(TYPE_ORANGE == type){
return new Orange("Peter",80);
} else if(TYPE_BANANA == type){
return new Banana();
}
return null;
}
/**
* 多方法工厂
* @return
*/
public static Fruit getFruitApple(){
return new Apple();
}
public static Fruit getFruitOrange(){
return new Orange("Peter",80);
}
public static Fruit getFruitBanana(){
return new Banana();
}
}
总的来说,简单工厂模式就是用一个专业类(工厂类)来负责一种产品(水果类)的对象创建
简单工厂模式不属于23种设计模式,是工厂模式的基础.
思考?若工厂生产的产品越来越多,静态工厂不断修改,方法扩展极为庞大,产品品种扩展不优雅.
- 1.不符合单一职责原则:一个类负责了各类水果的创建.
- 2.不符合开闭原则:扩展品种时,需要修改已有代码,修改工厂类.
工厂方法模式
为了解决静态工厂的问题,我们采用工厂方法模式
- 1.将静态工厂打散,每一个水果品类,对应一个水果品类工厂来生产。
- 2.当需要扩展水果品类时,对应扩展一个水果品种的工厂即可。
将工厂类抽象出一个接口,对象的创建方法延迟到工厂子类去实现.
/**
* 工厂方法接口
*/
public interface FruitFactory {
public Fruit getFruit();//摘水果指令
}
/**
* 橘子工厂子类
*/
public class OrangeFactory implements FruitFactory{
public Fruit getFruit(){
return new Orange("Peter",80);
}
}
/**
* 香蕉工厂子类
*/
public class BananaFactory implements FruitFactory{
public Fruit getFruit(){
return new Banana();
}
}
/**
* 苹果工厂子类
*/
public class AppleFactory implements FruitFactory{
public Fruit getFruit(){
return new Apple();
}
}
/**
* 水果获取测试
*
*/
public class FruitTest {
private static FruitFactory fruitFactory;
public static void main(String[] args) {
getFruit();
}
/**
* 获得水果
*/
public static void getFruit(){
//初始化苹果工厂
fruitFactory = new AppleFactory();
Fruit fruit = fruitFactory.getFruit();
fruit.draw();
//初始化香蕉工厂
fruitFactory = new BananaFactory ();
Fruit bananafruit = fruitFactory.getFruit();
bananafruit.draw();
//想要获取什么水果就实例化哪个工厂
}
}
通过工厂方法模式,解决了单一职责和开闭原则问题。
需要具体的产品则初始化对应的工厂,在spring中经常是配置在配置文件中,
//然后注入进去,面向接口编程我们注入的是接口实现类在配置里
@Autowired
private FruitFactory fruitFactory;
为什么使用抽象工厂模式
业务慢慢发展,现在水果店品种增加,那我们按着工厂方法模式新增其他工厂实现类。
现在除了卖水果的服务还要提供额外服务,比如要包装好,同样的我们就新建一个包装工厂接口如下BagFactory负责打包。
/**
* 工厂方法模式
*/
public interface BagFactory {
public Bag getBag();//打包指令
}
/**
* 负责香蕉的打包
*/
public class BananaBagFactory implements BagFactory{
public Bag getBag(){
return new BananaBag();
}
}
/**
* 负责苹果的打包
*/
public class AppleBagFactory implements BagFactory{
public Bag getBag(){
return new AppleBag();
}
}
一个水果店的动作,就有从工厂获取水果,然后从工厂获取打包服务,如下:
/**
* 水果店测试
* Created by Peter on 10/8 008.
*/
public class FruitStoreTest {
private static FruitFactory fruitFactory;
private static BagFactory bagFactory;
public static void main(String[] args) {
pack();
}
/**
* 邮寄打包
*/
public static void pack(){
//初始化苹果工厂
fruitFactory = new AppleFactory();//猎取工厂不对应
Fruit fruit = fruitFactory.getFruit();
fruit.draw();
//初始化苹果包装工厂
bagFactory = new BananaBagFactory();
Bag bag = bagFactory.getBag();
bag.pack();
//....邮寄业务
}
产品类图如下:
同样的,要是再加一个邮寄业务,我们也是同样的新增一个邮寄工厂。
问题? 在实际写代码的时候是否会发生这种问题: 即猎取工厂不对应
- 1.初始化苹果工厂获取苹果
- 2.初始化香蕉工厂来做包装业务
- 3.初始化别的邮寄工厂来做邮寄服务
抽象工厂模式
针对上面的问题就要用到我们的抽象工厂模式了。
抽象工厂模式:当一个类别的产品还有多个系列区分时,为了按系列生产商品,使用抽象工厂区分。
比如不同水果有不同包装规格,客户下单时,自动配出包装,
- --生产苹果,配置纸箱包装
- --生产香蕉时,配置竹萝包装
PS:保证客户端只使用同一个产品族中的对象(如下代码的AppleFactory,BananaFactory)。
/**
* 抽象水果工厂
*/
public abstract class AbstractFactory {
public abstract Fruit getFruit();
public abstract Bag getBag();
}
/**
* 水果工厂
*/
public class AppleFactory extends AbstractFactory{
@Override
public Fruit getFruit() {
return new Apple();
}
@Override
public Bag getBag() {
return new AppleBag();
}
}
/**
* 水果工厂
*/
public class BananaFactory extends AbstractFactory{
@Override
public Fruit getFruit() {
return new Banana();
}
@Override
public Bag getBag() {
return new BananaBag();
}
}
/**
* 抽象工厂模式测试
* 按订单发送货品给客户
* Created by Peter on 10/8 008.
*/
public class OrderSendClient {
public static void main(String[] args){
sendFruit();
}
public static void sendFruit(){
//初始化工厂
AbstractFactory factory = new AppleFactory();//spring使用注入方式
//得到水果
Fruit fruit = factory.getFruit();
fruit.draw();
//得到包装
Bag bag = factory.getBag();
bag.pack();
//以下物流运输业务。。。。
}
}
抽象工厂模式类图:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。