前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之工厂模式

设计模式之工厂模式

作者头像
爱撒谎的男孩
发布2018-05-25 16:12:45
4530
发布2018-05-25 16:12:45
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

创建型模式之工厂模式

什么是工厂模式

  • 工厂模式是java中最常见的创建型模式,客户端在不知道创建逻辑的情况下,只需要在工厂中直接创建即可

简单工厂模式

  • 简单工厂在创建对象的时候不需要知道具体的创建逻辑,客户端只需要知道该产品的一个标志即可,比如产品的名字
  • 必备的两个元素:
    • 产品的抽象类
    • 生产产品的工厂类

实现

  • 假设现在我们需要根据客户端的要求创建不同的图形,比如矩形,圆形…..,此时我们可以将图形抽象成接口,具体的产品只需要实现这个图形接口即可
简单工厂模式
简单工厂模式

简单工厂模式

  • shape接口(图形的接口,其中提供了一个创建图形的方法)
代码语言:javascript
复制
/*
 * 这个是抽象的产品类,后续的所有的产品都必须实现这个抽象类
 */
public interface Shape {
	public void draw();   //提供一个实现方法,作为画画的动作
}
  • 矩形产品类(实现shape接口)
代码语言:javascript
复制
/*
 * 矩形的产品类,其中实现了Shape这个类
 */
public class Rectangle implements Shape {

	/**
	 * 实现了Shape中的方法
	 */
	@Override
	public void draw() {
		System.out.println("我们画了一个矩形");

	}

}
  • 圆形产品类(实现Shape接口)
代码语言:javascript
复制
/*
 * 圆形的产品类,实现了Shape这个类
 */
public class Circle implements Shape {

	@Override
	public void draw() {
		System.out.println("我们画了一个圆");

	}
}
  • 工厂方法(创建产品的类)
    • 根据传入的标志创建对应的产品
代码语言:javascript
复制
/*
 * 简单工厂的实例
 * 其中提供一个getShape(String name) 可以根据提供的名字来返回一个对象,其实工厂生产的产品
 */
public class SimpleFactoryDemo {
	public Shape getShape(String name) {
		switch (name) {
		case "矩形":
			return new Rectangle(); // 返回矩形的对象
		case "圆形":
			return new Circle(); // 返回圆形对象
		default:
			System.out.println("我们不能创建一个额外的对象");
			return null; // 没有指定对象就返回null
		}

	}
}
  • 测试
代码语言:javascript
复制
public class ClientMain {
	public static void main(String[] args) {
		String name = "圆形"; // 填入名字
		SimpleFactoryDemo simpleFactoryDemo = new SimpleFactoryDemo(); // 创建简单工厂实例
		Shape shape = simpleFactoryDemo.getShape(name); // 根据名字获取对象
		shape.draw(); // 调用方法
	}
}

优缺点

  • 优点:
    • 每次增加一个产品类只需要增加一个实现类即可(实现产品接口)
  • 缺点:
    • 如果添加一个产品类,那么我们就需要在工厂类中添加对应的代码(违反开闭原则)
    • 开闭原则:
      • 简单的说就是在对功能进行扩展的时候对原先的代码不做任何修改

工厂方法模式

  • 简单工厂模式是一个抽象产品类派生出多个具体的产品类,但是一个工厂就生产了全部的产品
  • 工厂方法模式是有一个抽象工厂派生出多个具体的工厂,每个工厂生产一件具体的产品

条件

  1. 抽象产品类
  2. 抽象工厂类
  3. 每个具体的产品类都有一个具体的工厂类生产

实现

  • 我们对上面的实例进行改写,只需要定义一个抽象工厂类即可,其中派生出两个具体的工厂类用来生产圆形和矩形
  • 这里的抽象产品接口和具体的产品类和上面相同,不需要写了
  • 抽象工厂(使用的接口,其中有一个生产方法)
代码语言:javascript
复制
/*
 * 抽象的工厂类
 * 其中定义一个方法 getShape() 返回的是Shape类型的产品类
 */
public interface FactoryInterface {
	public Shape getShape();
}
  • 生产圆形的工厂类(实现抽象工厂)
代码语言:javascript
复制
/*
 * 生产圆形的产品类  其中实现了抽象的工厂类
 */
public class FactoryCircle implements FactoryInterface {

	@Override
	public Shape getShape() {
		return new Circle();
	}

}
  • 生产矩形的工厂类(实现抽象工厂接口)
代码语言:javascript
复制
/**
 * 生产矩形的工厂类,其中实现了抽象工厂类
 */
public class FactoryRectangle implements FactoryInterface {
	@Override
	public Shape getShape() {
		return new Rectangle();
	}
}
  • 测试类
代码语言:javascript
复制
public class ClientMain {
	public static void main(String[] args) {
		//使用多态创建工厂类
		FactoryInterface factoryInterface=new FactoryCircle();  //创建圆形的工厂类
		factoryInterface.getShape().draw();  //生成Circle对象并且调用方法

		FactoryInterface factoryInterface2=new FactoryRectangle();  //创建矩形的工厂类
		factoryInterface2.getShape().draw();   //生成Rectangle的对象并且调用方法


	}
}

优缺点

  • 优点:
    • 易于扩展,如果需要添加一个产品类,只需要添加一个具体的产品类和对应的工厂类即可,不需要对原工厂的方法进行任何的修改
    • 在工厂方法模式中,用户只需要知道所需要产品的具体工厂类即可,不需要知道具体的创建过程,甚至不需要知道具体产品类的类名。
  • 缺点:
    • 每次新增一个产品时,都需要增加一个具体的产品类和具体的工厂类,明显的成倍增加代码。

抽象工厂模式

  1. 多个抽象产品类,派生出多个具体产品类;一个抽象工厂类,派生出多个具体工厂类;每个具体工厂类可创建读个具体产品类实例。
  2. 即是提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体的类。“一对多的关系”
  3. 这里的抽象产品类就像是一类产品的族,其中具体实现类就是不同的表现形式而已。
  4. 这里的每一个具体的工厂类可以生产不同种类的产品,并不是一个具体的工厂类只能生产一个具体的产品罢了
  5. 下面我们举一个麦当劳和肯德基的例子,他们两家中都买薯条和鸡翅,那么薯条和鸡翅就是两类产品,麦当劳和肯德基就是具体的工厂类用来生产薯条和鸡翅,那么我们需要一个抽象的工厂类来生产这两类产品,肯德基和麦当劳只需要实现即可。

总结定义

  • 简单的说:
    • 抽象工厂模式一个一个工厂生产一个产品类族
    • 其中的工厂并不是生产一种产品,而是生产多种产品(一类的产品)

条件

  • 多个抽象产品类派生出多个具体的产品类,比如鸡翅(麦当劳,肯德基),薯片(麦当劳,肯德基)
  • 一个抽象工厂,派生出多个具体的工厂类,比如肯德基和麦当劳就相当于两个工厂,这两个工厂都生产各自品牌的鸡翅,薯片,汉堡等

实现

  • 抽象产品类
    • 这里我们有两种产品,一个是鸡翅,一个薯片,因此需要创建两个抽象产品接口
    • 鸡翅的抽象接口
    • 薯片的抽象接口
    代码语言:javascript
    复制
    /*
    	* 薯条的接口,这也是一个抽象的产品类,其中可以有多个具体的产品类,比如麦当劳的薯条,肯德基的薯条
    	*/
    public interface IChips {
    	public void eat();
    }
代码语言:javascript
复制
/*
	* 鸡翅的接口,这是一类产品的接口,在其中可以实现具体的产品类,比如麦当劳的麦乐鸡,肯德基的奥尔良烤翅
*/
public interface IChicken {
public void eat();

}
  • 抽象工厂类
    • 抽象工厂类只有一个,但是具体的工厂类一个是麦当劳,一个肯德基,工厂中生产各自品牌的产品
    • 抽象工厂
代码语言:javascript
复制
/*
	* 抽象工厂类,用来生产鸡翅和薯条的工厂类,下面可以衍生出多个具体的工厂类来生产指定商家的鸡翅和薯条
	*/

public interface IStore {

	public IChicken createChicken(); // 生产鸡翅

	public IChips createChips(); // 生产薯条
}
  • 具体的产品类
    • 肯德基的薯条
    • 肯德基的鸡翅
    代码语言:javascript
    复制
    /*
    	* 肯德基的奥尔良烤翅类,是IChicken的具体实现类,是一个具体的产品
    	*/
    public class KfcChicken implements IChicken {
    
    	@Override
    	public void eat() {
    		System.out.println("你吃了肯德基的奥尔良烤翅......");
    
    	}
    }
    • 麦当劳的薯条
    代码语言:javascript
    复制
    /**
    	* 麦当劳的薯条,是IChips具体实现类,也是一个具体的产品类
    	*/
    public class McChips implements IChips {
    
    	@Override
    	public void eat() {
    		System.out.println("你吃了麦当劳的薯条......");
    
    	}
    }
    • 麦当劳的鸡翅
    代码语言:javascript
    复制
    /*
    	* 麦当劳的鸡翅,这是IChicken的具体的实现产品类
    	*/
    public class McChicken implements IChicken {
    
    		@Override
    		public void eat() {
    			System.out.println("你吃了的麦当劳的鸡翅......");
    
    		}
    	}
代码语言:javascript
复制
/**
 * 肯德基的薯条,是IChips具体实现类,也是一个具体的产品类
 */
public class KfcChips implements IChips {

	@Override
	public void eat() {
		System.out.println("你吃了肯德基的薯条......");

	}

 }
  • 具体的工厂类
    • 麦当劳的工厂类
    • 肯德基的工厂类
    代码语言:javascript
    复制
    /*
    	* 肯德基的工厂,实现了抽象工厂,这个工厂可以生产肯德基的鸡翅和薯条
    	*/
    public class KFCFactory implements IStore {
    
    	@Override
    	public IChicken createChicken() {
    		return new KfcChicken(); // 生产肯德基的鸡翅
    	}
    
    	@Override
    	public IChips createChips() {
    		return new KfcChips(); // 生产肯德基的薯条
    	}
    
    }
代码语言:javascript
复制
/*
	* 麦当劳的工厂,实现了抽象工厂,这个工厂可以生产麦当劳的鸡翅和薯条
	*/
public class McFactory implements IStore {

	@Override
	public IChicken createChicken() {
		return new McChicken(); // 生产麦当劳的鸡翅
	}

	@Override
	public IChips createChips() {
		return new McChips(); // 生产麦当劳的薯条
	}

}
  • 测试类
代码语言:javascript
复制
public class ClientMain {

	public static void main(String[] args) {

		IStore iStore1=new KFCFactory();   //创建肯德基的具体工厂类
		iStore1.createChicken().eat();    //吃了肯德基的鸡翅
		iStore1.createChips().eat();    //吃了肯德基的薯条

		IStore iStore2=new McFactory();   //创建麦当劳的具体工厂类
		iStore2.createChicken().eat();    //吃了麦当劳的鸡翅
		iStore2.createChips().eat();   //吃了麦当劳的薯条
	}

}

优缺点

  • 优点
    • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
  • 缺点
    • 产品族比较难扩展,比如你要添加一个鞋子这个产品族,那么需要自己定义一个鞋子的抽象产品类,还要添加这个不同品牌的具体的产品实现类,另外还需要在抽象工厂里添加一个生产鞋子的方法
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建型模式之工厂模式
    • 什么是工厂模式
      • 简单工厂模式
        • 实现
        • 优缺点
      • 工厂方法模式
        • 条件
        • 实现
        • 优缺点
      • 抽象工厂模式
        • 总结定义
        • 条件
        • 实现
        • 优缺点
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档