1、现有一个水果蔬菜项目,需要根据传参的不同生成不同的水果对象
2、以面向对象的原则设计这个项目
1)抽象出一个接口Fruit
public interface Fruit {
void get();
}
2) 创建接口实现类Apple、Banana
Banana:
public class Banana implements Fruit {
@Override
public void get() {
System.out.println("This is Banana");
}
}
Apple:
public class Appleimplements Fruit {
@Override
public void get() {
System.out.println("This is Apple");
}
}
3)创建一个蔬菜工厂,根据参数不同创建不同的水果对象
public class FruitFactory {
public static Fruit createFruit(String type)throws IllegalAccessException, InstantiationException {
if(type.equals("apple")){
return Apple.class.newInstance();
}else if(type.equals("banana")){
return Banana.class.newInstance();
}
return null;
}
}
4)运行
传入不同的参数,获取不同的对象
public static void main(String[] args)throws InstantiationException, IllegalAccessException {
Fruit apple = FruitFactory.createFruit("apple");
Fruit banana = FruitFactory.createFruit("banana");
apple.get();
banana.get();
}
结果:
This is Apple
This is Banana
这是典型的简单工厂模式,但是这种方式有问题,若需要新增一个水果类型,需要修改FruitFactory方法新增个else if,另外还需新增个水果类。这就违反了设计模式的开放-封闭原则。接下来我会采用工厂模式改造这个项目
3、利用工厂模式改造项目
1)在原来的基础上改造FruitFactory,把FruitFactory抽象成一个接口
public interface FruitFactory {
Fruit createFruit();
}
2)生成一个抽象工厂的实现类AppleFactory,里面创建一个Apple对象
public class AppleFactroyimplements FruitFactory {
@Override
public FruitcreateFruit() {
return new Apple();
}
}
3)运行
public static void main(String[] args) {
FruitFactory appleFactory =new AppleFactroy();
FruitFactory bananaFactory =new BananaFactory();
Fruit apple = appleFactory.createFruit();
Fruit banana = bananaFactory.createFruit();
apple.get();
banana.get();
}
结果:
This is Apple
This is Banana
利用工厂设计模式就解决了之前简单工厂模式出现的问题,如果需要新增一个水果,只需两步:1、新增水果对象。2、新增生成这个水果对象的对应的工厂。
4、工厂模式
1)定义
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
2)工厂模式结构图
3)工厂模式的角色和职责
1、抽象工厂角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。(抽象工厂角色里包含获取抽象产品角色的方法)(本例中的抽象工厂角色是FruitFactory)
2、具体工厂角色:具体工厂类是抽象工厂的一个实现,负责实例化产品对象。(本例中的具体工厂角色是AppleFactory、BananaFactory)
3、抽象产品角色:工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。(本例中的抽象产品角色是Fruit)
4、具体产品角色:工厂方法模式创建的具体实例(本例中的具体产品角色是Apple、Banana)
5、工厂模式出现的问题。
看似工厂模式已经很好了,抽象工厂生成出不同的具体产品工厂,然后具体产品工厂生产出具体的产品。但是我们思考这样一个问题:如果具体产品还能往下分类,例如上例中的苹果我要分为南方苹果、北方苹果,这时上面工厂模式就无法解决这个问题,无法生产出具体的南方苹果或北方苹果。这是有人就会想,我们新建一个北方苹果或南方苹果类,在苹果工厂的获取苹果对象方法上加个参数,根据传入不同参数的苹果获取不同的对象,但这样就又出现问题了,这又违反了设计模式的基本原则:开放-封闭原则。新增一个温室苹果的话又要修改苹果工厂代码。那这个问题我们需要怎么解决呢?接下来引入抽象工厂设计模式解决这个问题。
6、利用抽象工厂模式重构这个项目。
1)在原有的Apple、Banana类上,改造封装成抽象类,形成一个产品族(苹果产品族、香蕉产品族)
苹果产品
public abstract class Apple implements Fruit { }
香蕉产品
public abstract class Banana implements Fruit {}
2)修改抽象工厂接口,改成获取产品族对象。
public interface FruitFactory {
/**
* 获取苹果实例
*/
FruitgetApple();
/**
* 获取香蕉实例
*/
FruitgetBanana();
}
3)具体工厂实现类
public class NorthFruitFactory implements FruitFactory{
@Override
public Fruit getApple() {
return new NorthApple();
}
@Override
public Fruit getBanana() {
return new NorthBanana();
}
}
4)具体产品实习类NorthApple、SouthApple
NorthApple
public class NorthAppleextends Apple {
@Override
public void get() {
System.out.println("This is NorthApple");
}
}
SouthApple
public class SouthAppleextends Apple {
@Override
public void get() {
System.out.println("This is SouthApple");
}
}
5)运行
public static void main(String[] args) {
FruitFactory north =new NorthFruitFactory();
Fruit northApple = north.getApple();
Fruit northBanana = north.getBanana();
northApple.get();
northBanana.get();
}
结果
This is NorthApple
This is NorthBanana
8、抽象工厂模式
1)定义
抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。
2)抽象工厂模式中的角色和职责
1.抽象工厂(Creator)角色(本例中的抽象工厂角色是FruitFactory)
抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。
2.具体工厂( Concrete Creator)角色(本例中的具体工厂角色是NorthFactory)
具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。
3.抽象(Product)角色(本例中的抽象角色是Fruit)
抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
4.具体产品(Concrete Product)角色(本例中的具体产品角色是SouthApple等)
抽象模式所创建的具体实例对象
总结:抽象工厂中方法对应产品结构,具体工厂对应产品族。