概述: 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。不是23种模式中的一种,是一种编码习惯。
优点
1.工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
2.客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
3.通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
4.简单工厂模式最大的优点在于工厂类中可以判断客户的的选择来动态实例化相关的类,对于客户端来说,去除了具体产品的依赖。
缺点
1.由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
2.使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
3.系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,同样破坏了“开闭原则”;在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
4.简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
5.很明显工厂类集中了对所有实例创建的逻辑,如果我们要新增子类或者改变方法的话,就得每次都修改工厂类里面的代码,工厂类中的代码就会十分臃肿,
这就等于说我们不进开放了扩展,还开放了修改,这样就违反了开放-封闭原则。
需求:设计一个咖啡店点餐系统。
设计一个咖啡类(Coffee),并定义其两个子类(美式【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。
/**
* @Description: 咖啡类
*/
public abstract class Coffee {
public abstract String getName();
//加糖
public void addsugar() {
System.out.println("加糖");
}
//加奶
public void addMilk() {
System.out.println("加奶");
}
}
美式咖啡类
/**
* @Description: 美式咖啡
*/
public class AmericanCoffee extends Coffee {
public String getName() {
return "美式咖啡";
}
}
拿铁咖啡类
/**
* @Description: 拿铁咖啡
*/
public class LatteCoffee extends Coffee {
public String getName() {
return "拿铁咖啡";
}
}
咖啡店类
/**
*咖啡店类
*/
public class CoffeeStore {
public Coffee orderCoffee(String type) {
//声明Coffee类型的变量,根据不同类型创建不同的coffee子类对象
Coffee coffee = null;
if("american".equals(type)) {
coffee = new AmericanCoffee();
} else if("latte".equals(type)) {
coffee = new LatteCoffee();
} else {
throw new RuntimeException("对不起,您所点的咖啡没有");
}
//加配料
coffee.addMilk();
coffee.addsugar();
return coffee;
}
}
测试类
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
//1,创建咖啡店类
CoffeeStore store = new CoffeeStore();
//2,点咖啡
Coffee coffee = store.orderCoffee("american");
System.out.println(coffee.getName());
}
}
这里的咖啡店与咖啡种类耦合严重,当我们新增一个咖啡类型时,势必会修改咖啡店类中的代码,违背了开闭原则。
在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。
如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;
所以说,工厂模式最大的优点就是:解耦。
简单工厂不是一种设计模式,反而比较像是一种编程习惯。
简单工厂包含如下角色:
抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
具体产品 :实现或者继承抽象产品的子类
具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。
/**
* @Description: 咖啡类
*/
public abstract class Coffee {
public abstract String getName();
//加糖
public void addsugar() {
System.out.println("加糖");
}
//加奶
public void addMilk() {
System.out.println("加奶");
}
}
美式咖啡类
/**
* @Description: 美式咖啡
*/
public class AmericanCoffee extends Coffee {
public String getName() {
return "美式咖啡";
}
}
拿铁咖啡类
/**
* @Description: 拿铁咖啡
*/
public class LatteCoffee extends Coffee {
public String getName() {
return "拿铁咖啡";
}
}
简单咖啡工厂类,专门生产咖啡
/**
* @Description: 简单咖啡工厂类,用来生产咖啡
*/
public class SimpleCoffeeFactory {
public Coffee createCoffee(String type) {
//声明Coffee类型的变量,根据不同类型创建不同的coffee子类对象
Coffee coffee = null;
if("american".equals(type)) {
coffee = new AmericanCoffee();
} else if("latte".equals(type)) {
coffee = new LatteCoffee();
} else {
throw new RuntimeException("对不起,您所点的咖啡没有");
}
return coffee;
}
}
咖啡店类
/**
* 咖啡店,调配咖啡
*/
public class CoffeeStore {
public Coffee orderCoffee(String type) {
SimpleCoffeeFactory factory = new SimpleCoffeeFactory();
//调用生产咖啡的方法
Coffee coffee = factory.createCoffee(type);
//加配料
coffee.addMilk();
coffee.addsugar();
return coffee;
}
}
测试类
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
//创建咖啡店类对象
CoffeeStore store = new CoffeeStore();
Coffee coffee = store.orderCoffee("latte");
System.out.println(coffee.getName());
}
}
工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。
这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。
后期如果再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。
工厂类的客户端可能有很多,比如创建美团外卖等,这样只需要修改工厂类的代码,省去其他的修改操作。
使用简单工程后的优缺点
优点:
封装了创建对象的过程,可以通过参数直接获取对象。
把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,
如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
缺点:
增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。
使用静态工厂(静态方法)
工厂类中的创建对象的功能定义为静态的,这个就是静态工厂模式。
咖啡店类内部直接使用类名调用
在简单工厂的代码上修改这两个地方就是静态工厂了,其他的不变
结束!!
当我遇到难题时我总是想逃避,总是想换个环境会好些,但从不考虑换个环境后会不会更糟糕。