属于创建型设计模式:分为简单工厂模式,方法工厂模式和抽象工厂模式
简单工厂模式:可以类比小作坊(只有一个车间,可以生产多种产品),用一个类来负责产生所有继承公共父接
口的产品类的实例,让用户可以只关心结果,不再关心生产的过程,直接告诉工厂类(类似到小作坊购买就行)
需求,隐藏了产品类的具体实现过程。(具体实现是:定义抽象产品可生产多个产品,然后用有个加工类负责实现这些产品)
UML:
工厂方法模式:类似规模化,标准化的大工厂,有生产各个具体产品的车间,这个时候工厂是抽象的,当生产某种具体的产品
时,需要指定特定的车间才能生产出来,也是对用户隐藏了产品的具体实现,只需要关心结果就行。(具体的实
现:定义一个抽象产品可生产多个产品,定义一个抽象工厂可生产多个具体的车间负责加工特定的产品)
UML:
抽象工厂模式:可以类比流水线,当产品里有多于一个的产品族(位于不同等级结构的相关联产品,比如同为鼠标,不同厂家生产的鼠标质量是不同的),
抽象模式可以解决接口选择的问题,向客户端提供一个接口,使客户端在不必指定具体产品的情况下,创建多个产品族中的产品对象。
(具体实现见代码)
UML:
简单工厂模式和工厂方法模式的优缺点和比较:
(1)两者结构不同,简单工厂模式只有一个多种产品的实现类,不易扩展,而且应为需要传入一个产品类参数才能获得相应的产品,容易出错,而工厂方法模式核心是一个抽象工厂类,可以根据抽象工厂类做工厂的扩展
(2)前者不符合开闭原则,因为当生产一个新产品时,必须修改实现类,后者只需要添加一个新的产品类和实现该产品具体工厂类就行,不需要修改客户端
(3)简单工厂模式客户端需要知道具体产的品类,而后者只需要知道相应的车间(工厂)就行
(4)工厂方法模式利用面向对象的多态性和里式代换原则,抽象工厂只提供生产某类产品的接口,有子类确定自己要生产的对象,使得系统易于扩展
(5)对于后者的缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,
同时也增加了系统具体类的依赖。这并不是什么好事。
抽象工厂的优缺点:
优点:当针对同组产品的创建新的生产线,容易增加。
缺点:新的产品族的扩展非常困难,需要修改抽象工厂,还需修改继承了抽象工厂的相应子工厂。灵活性差
简单工厂模式代码:(用牛奶举例子):
需要一个接口:牛奶(产生各种品牌的牛奶)
public interface Milk {
Milk getMilk();
}
伊利品牌牛奶 Implements Milk
public class YiLi implements Milk{
@Override
public Milk getMilk() {
return new YiLi();
}
}
蒙牛品牌的牛奶 implements Milk
public class Mengniu implements Milk {
@Override
public Milk getMilk() {
return new Mengniu();
}
}
简单工厂模式是用一个类实现所有的产品类:因此需要知道客户端传来的参数,也就是需要的产品是什么
public class Sinfactory {
public String getMilk(Milk milk) {
if(milk instanceof YiLi) {
return "已经获得伊利牛奶";
}else if(milk instanceof Mengniu) {
return "已经获得蒙牛";
}else {
return "无此产品";
}
}
}
工厂方法模式代码:(同样用牛奶举例子)
需要一个接口:牛奶(产生各种品牌的牛奶)
public interface Milk {
Milk getMilk();
}
伊利品牌牛奶 Implements Milk
public class YiLi implements Milk{
@Override
public Milk getMilk() {
return new YiLi();
}
}
蒙牛品牌的牛奶 implements Milk
public class Mengniu implements Milk {
@Override
public Milk getMilk() {
return new Mengniu();
}
}
然后不同于简单工厂模式:工厂方法是具体的工厂生产具体的产品
先定义一个抽象工厂接口
public interface AbstractFactory {
public String getMilk();
}
然后实现具体的工厂
蒙牛:
public class MengniuFactory implements AbstractFactory{
@Override
public String getMilk() {
return "Mengniu";
}
}
伊利
public class YiLiFactory implements AbstractFactory {
@Override
public String getMilk() {
return "YiLi";
}
}
抽象工厂方法代码实现(设计产品族,用电脑商品举例子)
一个电脑由:鼠标,键盘....组成
现在有华硕和戴尔都生产这两个产品,华硕生产的是华硕鼠标和华硕键盘,戴尔生产的是戴尔鼠标和戴尔键盘(因为质量不同,自然产生等级结构)
定义鼠标接口:
public interface Mouse {
public Mouse CreateMouse();
}
定义键盘接口
public interface KeyBoard {
public KeyBoard createKeyBoard();
}
实现华硕鼠标的生产:
public class SnsvMouse implements Mouse {
String name;
public SnsvMouse(String name) {
this.name = name;
}
@Override
public Mouse CreateMouse() {
return new SnsvMouse("SnsvMouse");
}
}
实现华硕键盘的生产
public class SnsvKeyBoard implements KeyBoard {
String name;
public SnsvKeyBoard(String name) {
this.name = name;
}
@Override
public KeyBoard createKeyBoard() {
return new SnsvKeyBoard("SnsvKeyBoard");
}
}
实现戴尔鼠标的生产
public class DellMouse implements Mouse {
String name;
public DellMouse(String name) {
this.name = name;
}
public DellMouse() {
}
@Override
public Mouse CreateMouse() {
return new DellMouse("DellMouse");
}
}
实现戴尔键盘的生产
public class DellKeyBoard implements KeyBoard{
String name;
public DellKeyBoard(String name) {
this.name = name;
}
@Override
public KeyBoard createKeyBoard() {
return new DellKeyBoard("DellKeyBoard");
}
}
定义一个抽象工厂:里面有获得产品(Mouse,KeyBoard)的方法
public abstract class AbstractPCFactory {
public abstract Mouse getMouse();
public abstract KeyBoard getKeyBoard();
}
华硕工厂产生具体的华硕产品
public class SnsvFactory extends AbstractPCFactory {
@Override
public Mouse getMouse() {
return new SnsvMouse("").CreateMouse();
}
@Override
public KeyBoard getKeyBoard() {
return new SnsvKeyBoard("").createKeyBoard();
}
}
戴尔工厂产生具体的戴尔产品
public class DellFactory extends AbstractPCFactory{
@Override
public Mouse getMouse() {
return new DellMouse().CreateMouse();
}
@Override
public KeyBoard getKeyBoard() {
return new DellKeyBoard("Kell");
}
}
电脑商城
public class PcMall {
private Mouse mouse;
private KeyBoard keyboard;
public void make(AbstractPCFactory factory) {
mouse = factory.getMouse();
keyboard = factory.getKeyBoard();
}
}
只要传入你想获得的产品,传入具体的工厂就行,就可以获得相应的多个产品族中的相应对象
借助代码的实现很容易发现:对于工厂模式,针对同组产品,只需要增加一个生产线,比如如果添加一个联想品牌电脑生产键盘和鼠标
只需要LenveoFactory类,Lenveo鼠标,Lenveo键盘就行
但是当要生产新的产品族,比如硬盘
就需要在AbstractPCFactory添加生产硬盘的方法,同时还要修改所有的继承该工厂的子工厂(如SnsvFactory和DellFactory),给他们增加生产硬盘的接口,因此显得不够灵活