暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

设计模式-工厂模式(简单工厂、工厂方法、抽象工厂)

总要有一个梦想或大或小 2020-11-18
346

 王刚师傅说:“不想杀鱼的可以交给热心摊主处理”。看来是深得工厂模式的精髓,将创建对象的步骤交给工厂来创建,对象创建将会更加的规范化



简单工厂模式(静态工厂模式)

定义

定义一个接口,其有多种实现类,当需要在不同场景下使用不同的子类的实例对象时,由工厂代为创建。

实现要素

一个抽象接口
多个抽象接口的实现类
一个可管理创建多个对象的工厂类

UML类图

代码实现

抽象接口Shape

public interface Shape {
void draw();
}

抽象接口实现类

public class Circle implements Shape {
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
public class Rectangle implements Shape {
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Square implements Shape {
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
    工厂类
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public static Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
 测试类
public class TestDemo {
public static void main(String[] args) {


//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = ShapeFactory.getShape("CIRCLE");


//调用 Circle 的 draw 方法
shape1.draw();


//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = ShapeFactory.getShape("RECTANGLE");


//调用 Rectangle 的 draw 方法
shape2.draw();


//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = ShapeFactory.getShape("SQUARE");


//调用 Square 的 draw 方法
shape3.draw();
}
}

优点

  • 将创建实例的方法交给工厂,使用者不必关心如何创建实例,实现了解耦

  • 实例化代码放在工厂中,更符合面向对象及面向接口编程,而不是面向实现编程

缺点

  • 工厂类中集中实现了所有实例的创建方法,一旦工厂类不能使用,整个系统都将受到影响

  • 违反了“开放-关闭原则”,一旦要新增新的产品类,必然要修改工厂类,随着产品类越来越多,工厂类的业务逻辑将会很复杂


工厂方法模式

定义

定义一个抽象产品接口,其有多种产品实现类,定义一个工厂接口,其有多种工厂实现类,每种工厂类负责一种产品的实例化,当需要在不同场景下使用不同的子类的实例对象时,由对应的工厂代为创建。

当新增一种产品类时,不再修改原本的工厂类,符合”开闭原则“,解决了简单工厂中出现的问题

实现要素

一个抽象接口
一个工厂接口
多个抽象接口的实现类
多个工厂接口的实现类

UML类图

代码实现

  定义产品接口
public interface Car {
//获取车的品牌
String getCarBrand();
}
定义工厂接口
public interface CarFactory {
Car createCar();
}


产品实现类-JiLiCar
public class JiLiCar implements Car{
public String getCarBrand() {
return "吉利星瑞";
}
}

产品实现类-WuLingCar
public class WuLingCar implements Car{
public String getCarBrand() {
return "五菱宏光";
}
}
工厂实现类-JiLiFactory
public class JiLiFactory implements CarFactory{
public Car createCar() {
return new JiLiCar();
}
}
工厂实现类-WuLingFactory
public class WuLingFactory implements CarFactory{
public Car createCar() {
return new WuLingCar();
}
}
测试类
public class TestDemo {
public static void main(String[] args) {
WuLingFactory wuLingFactory = new WuLingFactory();
System.out.println(wuLingFactory.createCar().getCarBrand());


JiLiFactory jiLiFactory = new JiLiFactory();
System.out.println(jiLiFactory.createCar().getCarBrand());
}
}

优点

  • 符合开闭原则,新增一个产品实现类时,不用修改工厂类

  • 符合单一职责原则,每种工厂只负责其对应的产品实例化,与其他无关

缺点

  • 当新增一个产品实现类,需要同时新增一个对应的工厂类,这样无疑会产生类爆炸,增加系统在编译时的负担

  • 对于工厂内部的方法符合”开闭原则“,但是使用工厂类的用户,仍然需要去实例化工厂类对象


抽象工厂模式

定义

在工厂方法模式中,一个工厂只能生产一种产品,那如果想要生产多种产品呢?就需要将产品工厂再向上抽象,使用抽象工厂模式

定义一个抽象产品工厂接口,抽象工厂接口中可以定义多种产品的”生产方法“

其有多个产品工厂实现类;既然是多种产品,就需要多种产品接口,且有多个产品实现类


由于该设计模式过于抽象,简要解释下接下来的例子

抽象工厂的”生产方法“生产手机和PAD

品牌(抽象工厂实现):华为工厂、小米工厂

产品(产品接口实现):手机、PAD

品牌+产品:华为手机、华为PAD、小米手机、小米PAD


实现要素

一个抽象工厂接口,定义多种产品的”生产方法”
多个抽象工厂实现类,实现产品的“生产方法”,用来生产产品
多个产品接口
多个产品接口的实现类

UML类图

代码实现

抽象产品工厂接口

public interface IProductFactory {
IphoneProduct productPhone();
IpadProduct productPad();
}

产品工厂实现类-HuaWeiProductFactory

public class HuaWeiProductFactory implements IProductFactory{
public IphoneProduct productPhone() {
return new HuaWeiPhone();
}


public IpadProduct productPad() {
return new HuaWeiPad();
}
}

产品工厂实现类-XiaoMiProductFactory

public class XiaoMiProductFactory implements IProductFactory{
public IphoneProduct productPhone() {
return new XiaoMiPhone();
}


public IpadProduct productPad() {
return new XiaoMiPad();
}
}

产品抽象接口-IpadProduct

public interface IpadProduct {
//看电影
void seeMovie();
//玩游戏
void playGame();
}


IpadProduct接口实现类-HuaWeiPad

public class HuaWeiPad implements IpadProduct{
public void seeMovie() {
System.out.println("我用华为Pad看电影");
}


public void playGame() {
System.out.println("我用华为Pad玩游戏");
}
}

IpadProduct接口实现-XiaoMiPad

public class XiaoMiPad implements IpadProduct{
public void seeMovie() {
System.out.println("我用小米Pad看电影");
}


public void playGame() {
System.out.println("我用小米Pad玩游戏");
}
}

产品抽象接口-IphoneProduct

public interface IphoneProduct {
//打电话
void call();
//照相
void takingPictures();
}

IphoneProduct接口实现-HuaWeiPhone

public class HuaWeiPhone implements IphoneProduct{
public void call() {
System.out.println("我用华为手机打电话");
}


public void takingPictures() {
System.out.println("我用华为手机照相");
}
}

IphoneProduct接口实现-XiaoMiPhone

public class XiaoMiPhone implements IphoneProduct{
public void call() {
System.out.println("我用小米手机打电话");
}


public void takingPictures() {
System.out.println("我用小米手机照相");
}
}

测试类

public class TestDemo {


public static void main(String[] args) {
XiaoMiProductFactory xiaoMiProductFactory = new XiaoMiProductFactory();
IphoneProduct xiaomiIphoneProduct = xiaoMiProductFactory.productPhone();
xiaomiIphoneProduct.call();
xiaomiIphoneProduct.takingPictures();
IpadProduct xiaomiIpadProduct = xiaoMiProductFactory.productPad();
xiaomiIpadProduct.playGame();
xiaomiIpadProduct.seeMovie();




HuaWeiProductFactory huaWeiProductFactory = new HuaWeiProductFactory();
IphoneProduct huaWeiIphoneProduct = huaWeiProductFactory.productPhone();
huaWeiIphoneProduct.call();
huaWeiIphoneProduct.takingPictures();
IpadProduct huaweiIpadProduct = huaWeiProductFactory.productPad();
huaweiIpadProduct.playGame();
huaweiIpadProduct.seeMovie();


}


}

测试结果

优点

  • 当多种产品族被设计在一起工作时,可以保证一个应用一次只能使用同一个系列中的对象,这一点很重要(比如,你在华为工厂里只能见到华为品牌的产品,不可能见到小米的产品)

缺点

  • 难以新增新的种类的产品,因为抽象工厂限制了可以生产的“产品种类“,例如,抽象工厂规定了只能生产手机和PAD,想要生产电脑,是不可以的

文章转载自总要有一个梦想或大或小,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论