1.简单工厂模式
定义:专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。
优点:简单,易于实现。把类的实例化交给工厂,易于解耦。
缺点:添加具体商品需要修改工厂类,违反OCP开放封闭原则。
结构:
代码实现:
package com.company.designPattern.factory;
import java.util.Scanner;
//定义一个接口
interface IFastFood{
void eat();
}
class Hamburger implements IFastFood{
@Override
public void eat() {
System.out.println("吃汉堡");
}
}
class Pizza implements IFastFood{
@Override
public void eat() {
System.out.println("吃披萨");
}
}
//定义一个类用来生产产品
class Factory{
//用static修饰,可以直接通过Factory类来调用getInstance方法。
public static IFastFood getInstance(String str){
if(str.equals("Hamburger")){
return new Hamburger();
}else if(str.equals("Pizza")){
return new Pizza();
}else{
System.out.println("没有您要的商品");
}
return null;
}
}
//客户端 实现具体的商品
public class Client {
private static void eatFastFood(IFastFood fastFood){
fastFood.eat();
}
public static void main(String[] args) {
Client client=new Client();
Scanner sc=new Scanner(System.in);
System.out.println("请输入您想要的商品:");
String goodsName=sc.next();
IFastFood goods=Factory.getInstance(goodsName);
client.eatFastFood(goods);
}
}
2.工厂方法模式
定义:定义一个用来创建对象的接口,让其子类决定实例化哪个类(具体商品),子类决定实例化延迟到子类。针对每个商品提供一个工厂类,在客户端中判断使用哪个工厂类创建对象。在客户端中决定调用哪个具体工厂类实例化对象。
举例:快餐接口(产品接口),实现接口的有汉堡和披萨(具体产品类)。工厂接口,实现工厂接口的有汉堡工厂和披萨工厂。
优点:
降低了代码耦合度,对象的生成交给子类去完成。
实现了开放封闭原则 。每次添加子产品,不需要修改原有代码。
缺点:
增加了代码量,每个具体产品都需要一个具体工厂。
当增加抽象产品 也就是添加一个其他产品族 需要修改工厂 违背OCP。
结构:
代码实现:
package com.company.designPattern.factory;
import java.util.Scanner;
//定义一个接口
interface IFastFood{
void eat();
}
class Hamburger implements IFastFood{
@Override
public void eat() {
System.out.println("吃汉堡");
}
}
class Pizza implements IFastFood{
@Override
public void eat() {
System.out.println("吃披萨");
}
}
//定义一个工厂接口用来生产产品
interface Factory{
IFastFood getInstance();
}
//定义汉堡工厂实现生产
class HamburgerFactory implements Factory{
@Override
public IFastFood getInstance() {
return new Hamburger();
}
}
//定义披萨汉堡实现工厂
class PizzaFactory implements Factory{
@Override
public IFastFood getInstance() {
return new Pizza();
}
}
//客户端 实现具体的商品
public class Client {
public void eatFastFood(IFastFood fastFood){
fastFood.eat();
}
public static void main(String[] args) {
Client client=new Client();
Factory factory=new PizzaFactory();
client.eatFastFood(factory.getInstance());
}
}
3.抽象工厂模式
定义:提供一个一系列相关或相互依赖对象的接口,而无需指定它们具体的类。和工厂方法模式相似,可以这么理解:当工厂只生产一个商品时,即为工厂方法模式;当工厂生产两个或多个产品时,为抽象工厂模式。
举例:汉堡要搭配奶茶,那么汉堡工厂将生产汉堡和奶茶两个商品;披萨要搭配可乐,因此披萨工厂既要生产披萨,又要生产可乐。
优点:
代码解耦
实现多个产品族(相关联产品组成的家族),而工厂方法模式的单个产品,可以满足更多的生产需求
很好的满足OCP开放封闭原则
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类 对于复杂对象的生产
相当灵活易扩展
缺点:
扩展产品族相当麻烦 而且扩展产品族会违反OCP,因为要修改所有的工厂
由于抽象工厂模式是工厂方法模式的扩展 总体的来说 很笨重。
结构:
代码实现:
package com.company.designPattern.factory;
import java.util.Scanner;
//定义一个快餐接口
interface IFastFood{
void eat();
}
class Hamburger implements IFastFood{
@Override
public void eat() {
System.out.println("吃汉堡");
}
}
class Pizza implements IFastFood{
@Override
public void eat() {
System.out.println("吃披萨");
}
}
//定义一个饮料接口
interface Drink{
void drink();
}
class MilkyTea implements Drink{
@Override
public void drink() {
System.out.println("喝奶茶");
}
}
class Cola implements Drink{
@Override
public void drink() {
System.out.println("喝可乐");
}
}
//定义一个工厂接口用来生产产品
interface Factory{
IFastFood getInstance();
Drink getDrink();
}
//定义汉堡工厂实现生产
class HamburgerFactory implements Factory{
@Override
public IFastFood getInstance() {
return new Hamburger();
}
@Override
public Drink getDrink() {
return new MilkyTea();
}
}
//定义披萨汉堡实现工厂
class PizzaFactory implements Factory{
@Override
public IFastFood getInstance() {
return new Pizza();
}
@Override
public Drink getDrink() {
return new Cola();
}
}
//客户端 实现具体的商品
public class Client {
public void eatFastFood(IFastFood fastFood,Drink dr){
fastFood.eat();
dr.drink();
}
public static void main(String[] args) {
Client client=new Client();
Factory factory=new PizzaFactory();
client.eatFastFood(factory.getInstance(),factory.getDrink());
}
}
4.简单工厂模式vs工厂方法模式
在创建产品对象时,简单工厂类在工厂类中实例化对象,如果要增加新的产品,就要对工厂类的代码进行修改,不符合开闭原则(OCP原则);而工厂方法模式对每个产品都有具体的工厂实现这个类,当新增加产品时,只需要新添加产品类和工厂类即可,符合OCP原则。但是在客户端就必须要感知到具体的工厂类,也就是将判断逻辑由简单工厂的工厂类挪到客户端。
工厂方法模式横向扩展很方便。假如该工厂又有新的类,那么只需要创建相应的工厂类和产品类去实现抽象工厂接口和抽象产品接口即可。
5.改进的工厂设计模式
请参见本博主的另外两篇文章:
Java反射机制(一)在工厂类中利用反射获取对象,改进了简单工厂模式,使得在新增加商品时,不需要修改工厂类的代码。
Java之Annotation利用注解,在注解上设置要生产的产品,大大简化了代码。