您的位置:首页 > 其它

23种设计模式—— 工厂设计模式

2018-03-09 17:35 78 查看

定义:

定义了一个创建产品对象的工厂接口,将实际创建工作推迟到子类工厂当中。

场景模拟:

一个面条项目的方案设计
面条项目:要方便面条品种的扩展,要便于维护,要能运行时扩展


面条类设计:



面条工厂设计:if....else if....else


一、普通oop设计方式

/*
* 面条父类
*/
public abstract class Noodles {
// 面条名称
String name;
// 每种面条制作方式不同,声明为抽象方法
public abstract void make();
// 模拟定义为每种面条打包方式一致
public void box() {
System.out.println(name + " 打包;");
}
}

/*
* 麻辣面
*/
public class MLNoodles extends Noodles {
@Override
public void make() {
this.name = "麻辣面";
System.out.println(name + "制作;");
}
}

/*
* 牛肉面
*/
public class BeefNoodles extends Noodles {
@Override
public void make() {
this.name = "牛肉面";
System.out.println(name + "制作;");
}
}

/*
* 兰州拉面
*/
public class LZNoodles extends Noodles {
@Override
public void make() {
this.name = "兰州拉面";
System.out.println(name + "制作;");
}
}

/*
* 面条订单
*/
public class OrderNoodles {
public OrderNoodles() {
Noodles noodles = null;
String ordertype;
do {
ordertype = gettype();

if (ordertype.equals("ml")) {
// 选择了麻辣面
noodles = new MLNoodles();
} else if (ordertype.equals("beef")) {
// 选择了牛肉面
noodles = new BeefNoodles();
} else if (ordertype.equals("lz")) {
// 选择了兰州拉面
noodles = new LZNoodles();
} else {
break;
}
noodles.box();
} while (true);
}

private String gettype() {
//接收用户选择
Scanner scan = new Scanner(System.in);
System.out.println("请选择您要点的面");
String str = scan.next();
return str;
}
}

/*
* 主方法测试
*/
public class NoodlesStroe {
public static void main(String[] args) {
OrderNoodles orderNoodles;
orderNoodles = new OrderNoodles();

}

}


总结:

目前的需求解决了,但是一旦新增面条种类,需要修改订单部分的代码,违反了java开闭原则(Open Close Principle),不合理。

二、简单工厂模式:定义一个实例化面条的类,封装创建对象的代码

/*
* 面条父类同上
*/

/*
* 简单工厂
*/
public class SimpleNoodlesFactory {

//实例化面条对象
public Noodles CreateNoodles(String ordertype) {
Noodles noodles = null;

if (ordertype.equals("ml")) {
// 选择了麻辣面
noodles = new MLNoodles();
} else if (ordertype.equals("beef")) {
// 选择了牛肉面
noodles = new BeefNoodles();
} else if (ordertype.equals("lz")) {
// 选择了兰州拉面
noodles = new LZNoodles();
}
return noodles;

}

}

/*
* 面条订单
*/
public class OrderNoodles {
SimpleNoodlesFactory simpleNoodlesFactory;

public OrderNoodles(SimpleNoodlesFactory simpleNoodlesFactory) {

setFactory(simpleNoodlesFactory);
}

public void setFactory(SimpleNoodlesFactory simpleNoodlesFactory) {
Noodles noodles = null;
String ordertype;

this.simpleNoodlesFactory = simpleNoodlesFactory;

do {
ordertype = gettype();
noodles = simpleNoodlesFactory.CreateNoodles(ordertype);
if (noodles != null) {
noodles.make();
noodles.box();
}
} while (true);

}

private String gettype() {
//接收用户选择
Scanner scan = new Scanner(System.in);
System.out.println("请选择您要点的面:");
String str = scan.next();
return str;
}

}

/*
* 主方法测试
*/
public class NoodlesStroe {
public static void main(String[] args) {
//实例化工厂
SimpleNoodlesFactory simpleNoodlesFactory=new SimpleNoodlesFactory();
//创建订单
OrderNoodles orderNoodles;
orderNoodles = new OrderNoodles(simpleNoodlesFactory);
}
}


总结:

解决了上个方案遗留的问题,再次新加对象种类时,无需修改订单部分代码。但项目进一步扩展,在不同地区开展加盟店,然而每个地区制作出的口味不同,进而利用工厂方法模式进行设计。

三、工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类(针对每一种产品提供一个工厂类 。通过不同的工厂实例来创建不同的产品实例)

/*
* 北京牛肉面
*/
public class BJBeefNoodles extends Noodles {
@Override
public void make() {
this.name = "北京牛肉面";
System.out.println(name+"制作;");
}
}

/*
* 北京麻辣面
*/
public class BJMLNoodles extends Noodles {
@Override
public void make() {
this.name = "北京麻辣面";
System.out.println(name+"制作;");
}
}

/*
* 上海牛肉面
*/
public class SHBeefNoodles extends Noodles {
@Override
public void make() {
this.name = "上海牛肉面";
System.out.println(name+"制作;");
}
}

/*
* 上海麻辣面
*/
public class SHMLNoodles extends Noodles {
@Override
public void make() {
this.name = "上海麻辣面";
System.out.println(name+"制作;");
}
}

/*
* 工厂方法模式——抽象订单类
*/
public abstract class OrderNoodles {
public OrderNoodles() {
Noodles noodles = null;
String ordertype;
do {
ordertype = gettype();
noodles = createNoodles(ordertype);
noodles.make();
noodles.box();
} while (true);
}

//实例化对象由加盟店具体实例化
abstract Noodles createNoodles(String ordertype);

private String gettype() {
//接收用户选择
Scanner scan = new Scanner(System.in);
System.out.println("请选择您要点的面:");
String str = scan.next();
return str;
}
}

/*
* 北京订单类
*/
public class BJOrderNoodles extends OrderNoodles {
@Override
Noodles createNoodles(String ordertype) {
Noodles noodles = null;
if (ordertype.equals("ml")) {
noodles = new BJMLNoodles();
} else if (ordertype.equals("beef")) {
noodles = new BJBeefNoodles();
}
return noodles;
}
}

/*
* 上海订单类
*/
public class SHOrderNoodles extends OrderNoodles {
@Override
Noodles createNoodles(String ordertype) {
Noodles noodles = null;

if (ordertype.equals("ml")) {
noodles = new SHMLNoodles();
} else if (ordertype.equals("beef")) {
noodles = new SHBeefNoodles();
}
return noodles;
}
}

/*
* 主方法测试
*/
public class NoodlesStroe {
public static void main(String[] args) {
OrderNoodles orderNoodles;
orderNoodles = new SHOrderNoodles();
}
}


总结:

此次改进后,只需在主方法中实例化不同的OrderNoodles对象,就可以体验不同地区的Noodles。

四、抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类(抽象工厂往往有多种方法,可以生产多种产品,即产品簇,比如工厂还可以生产饼,汤等等)。

/*
* 抽象工厂
*/
public interface AbsFactory {
public Noodles CreateNoodles(String ordertype) ;
}

/*
* 北京工厂
*/
public class BJFactory implements AbsFactory {
@Override
public Noodles CreateNoodles(String ordertype) {
Noodles noodles = null;
if (ordertype.equals("ml")) {
noodles = new BJMLNoodles();
} else if (ordertype.equals("beef")) {
noodles = new BJBeefNoodles();
}
return noodles;
}
}

/*
* 上海工厂
*/
public class SHFactory implements AbsFactory {
@Override
public Noodles CreateNoodles(String ordertype) {
Noodles noodles = null;
if (ordertype.equals("ml")) {
noodles = new SHMLNoodles();
} else if (ordertype.equals("beef")) {
noodles = new SHBeefNoodles();
}
return noodles;
}
}

/*
* 抽象工厂模式——订单类
*/
public class OrderNoodles {
AbsFactory mFactory;

public OrderNoodles(AbsFactory mFactory) {
setFactory(mFactory);
}

public void setFactory(AbsFactory mFactory) {
Noodles noodles = null;
String ordertype;
this.mFactory = mFactory;
do {
ordertype = gettype();
noodles = mFactory.CreateNoodles(ordertype);
if (noodles != null) {
noodles.make();
noodles.box();
}
} while (true);
}

private String gettype() {
//接收用户选择
Scanner scan = new Scanner(System.in);
System.out.println("请选择您要点的面:");
String str = scan.next();
return str;
}
}

/*
* 主方法测试
*/
public class NoodlesStroe {
public static void main(String[] args) {
OrderNoodles orderNoodles;
orderNoodles = new OrderNoodles(new BJFactory());
}
}


抽象工厂模式与工厂方法模式的区别:

  抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

适用场景:

  无论是简单工厂模式,工厂方法模式还是抽象工厂模式,它们都具有类似的特性,适用场景也十分类似。他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。

  所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的,以后如果想组装其他的产品,只需要再增加一个工厂类的实现就可以。无论是灵活性还是稳定性都得到了极大的提高。

9a06
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 设计