工厂模式
先上代码:
//创建一个水果的接口
public interface Fruit {
void eat();
}
//创建实现水果接口的苹果实体类
public class Apple implements Fruit {
@Override
public void eat() {
System.out.println("eatApple");
}
}
//创建实现水果接口的橘子实体类
public class Orange implements Fruit {
@Override
public void eat() {
System.out.println("eatOrange");
}
}
//创建实现水果接口的香蕉实体类
public class Banana implements Fruit {
@Override
public void eat() {
System.out.println("eatBanana");
}
}
//创建一个水果工厂,生成基于给定信息的实体类对象
public class FruitFactory {
//使用 getFruit 方法获取形状类型的对象
public Fruit getFruit(String fruitType){
if(fruitType == null){
return null;
}
if(fruitType.equalsIgnoreCase("Apple")){
return new Apple();
} else if(fruitType.equalsIgnoreCase("Orange")){
return new Orange();
} else if(fruitType.equalsIgnoreCase("Banana")){
return new Banana();
}
return null;
}
}
//使用水果工厂,通过传递水果信息获取实体类的对象
public class FactoryFruitDemo {
public static void main(String[] args) {
FruitFactory fruitFactory = new FruitFactory();
//获取 Apple 的对象,并调用它的 draw 方法
Fruit fruit1 = fruitFactory.getFruit("Apple");
//调用 Apple 的 draw 方法
fruit1.eat();
//获取 Orange 的对象,并调用它的 draw 方法
Fruit fruit2 = fruitFactory.getFruit("Orange");
//调用 Orange 的 draw 方法
fruit2.eat();
//获取 Banana 的对象,并调用它的 draw 方法
Fruit fruit3 = fruitFactory.getFruit("Banana");
//调用 Banana 的 draw 方法
fruit3.eat();
}
}
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
抽象工厂模式
//创建一个水果的接口
public interface Fruit {
void eat();
}
//创建实现水果接口的苹果实体类
public class Apple implements Fruit {
@Override
public void eat() {
System.out.println("eatApple");
}
}
//创建实现水果接口的橘子实体类
public class Orange implements Fruit {
@Override
public void eat() {
System.out.println("eatOrange");
}
}
//创建实现水果接口的香蕉实体类
public class Banana implements Fruit {
@Override
public void eat() {
System.out.println("eatBanana");
}
}
//创建一个动物的接口
public interface Animal {
void say();
}
//创建实现动物接口的狮子实体类
public class Lion implements Animal {
@Override
public void say() {
System.out.println("I'm Lion");
}
}
//创建实现动物接口的狗实体类
public class Dog implements Animal {
@Override
public void say() {
System.out.println("I'm Dog");
}
}
//创建实现动物接口的猪实体类
public class Pig implements Animal {
@Override
public void say() {
System.out.println("I'm Pig");
}
}
//为Fruit和Animal对象创建抽象类来获取工厂
public abstract class AbstractFactory {
public abstract Fruit getFruit(String fruit);
public abstract Animal getAnimal(String animal);
}
//定义工厂继承查询工厂
public class MyFactory extends AbstractFactory {
//使用 getFruit 方法获取形状类型的对象
@Override
public Fruit getFruit(String fruitType){
if(fruitType == null){
return null;
}
if(fruitType.equalsIgnoreCase("Apple")){
return new Apple();
} else if(fruitType.equalsIgnoreCase("Orange")){
return new Orange();
} else if(fruitType.equalsIgnoreCase("Banana")){
return new Banana();
}
return null;
}
//使用 getAnimal 方法获取形状类型的对象
@Override
public Animal getAnimal(String animalType){
if(animalType == null){
return null;
}
if(animalType.equalsIgnoreCase("Lion")){
return new Lion();
} else if(animalType.equalsIgnoreCase("Dog")){
return new Dog();
} else if(animalType.equalsIgnoreCase("Pig")){
return new Pig();
}
return null;
}
}
//创建工厂创造器,通过传递种类获取不同的工厂
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("Fruit")){
return new MyFactory().getFruit();
} else if(choice.equalsIgnoreCase("Animal")){
return new MyFactory().getAnimal();
}
return null;
}
}
//通过传递类型信息来获取实体类的对象
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//获取形状工厂
AbstractFactory shapeFactory = FactoryProducer.getFactory("Fruit");
//获取形状为 apple 的对象
Fruit fruit = shapeFactory.getShape("Apple");
fruit.eat();
//省略.....
}
}
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
抽象工厂跟工厂模式的区别
工厂模式: 只有一个抽象产品类,具体工厂类只能创建一个具体产品类的实例
抽象工厂模式: 有多个抽象产品类 ,具体工厂类能创建多个具体产品类的实例