简单工厂
简单工厂模式又叫作静态工厂方法模式,有一个具体的工厂类,嗯可以生成多个不同的产品,属于创建型设计模式。
应用场景
对于产品种类相对较少的情况,考虑使用简单工厂模式可以很方便地创建所需产品。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑。
简单工厂模式主要包含3个角色:
- 简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。
- 抽象产品(IProduct):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
- 具体产品(ConcreteProduct):是简单工厂模式的创建目标。
package com.yab.simple;
/**
* IProduct 简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口
*/
public interface ITea{
//生产茶叶
public void productionTea();
}
package com.yab.simple;
/**
* ConcreteProduct 简单工厂模式的创建目标
*/
public class GreenTea implements ITea {
@Override
public void productionTea() {
System.out.println("生产绿茶");
}
}
package com.yab.simple;
public class RedTea implements ITea {
@Override
public void productionTea() {
System.out.println("生产红茶");
}
}
package com.yab.simple;
/**
* SimpleFactory:是简单工厂模式的核心,负责实现创建所有实例的内部逻辑
*/
public class TeaFactory extends RedTea {
public ITea create(String name){
if("greenTea".equals(name)){
return new GreenTea();
}else if("redTea".equals(name)){
return new RedTea();
}else {
return null;
}
}
}
package com.yab.simple;
public class Test extends TeaFactory {
public static void main(String[] args) {
TeaFactory teaFactory = new TeaFactory();
teaFactory.create("greenTea").productionTea();
}
}
到此一个简单工厂产生了。
当业务继续扩展,需要增加新种类的茶,工厂中的create()方法每次都要修改代码逻辑,不符合开闭原则。因此,可以采用反射,对简单工厂模式优化。
package com.yab.simple;
/**
* 反射优化工厂
*/
public class TeaFactoryRef {
public ITea createRef(String className){
try {
if(!(null==className || "".equals(className))){
return (ITea) Class.forName(className).newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.yab.simple;
public class TestRef {
public static void main(String[] args) {
TeaFactoryRef teaFactoryRef = new TeaFactoryRef();
ITea iTea = teaFactoryRef.createRef("com.yab.simple.RedTea");
iTea.productionTea();
}
}
优化之后,不在需要修改TeaFactoryRef中的代码。但还是有问题,方法参数是字符串(如果输错不就坑了自己),可控性待提升,而且还需要强制转型。
接着我们继续修改代码。
package com.yab.simple;
public class TeaFactoryLast {
public ITea createLast(Class<? extends ITea> teaClass){
try {
if(null != teaClass){
return teaClass.newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.yab.simple;
public class TestLast {
public static void main(String[] args) {
TeaFactoryLast teaFactoryLast = new TeaFactoryLast();
ITea iTea = teaFactoryLast.createLast(RedTea.class);
iTea.productionTea();
}
}
工厂方法模式
工厂方法模式又叫作多态性工厂模式,指定义一个创建对象的接口,但由实现这个接口的类来决定实例化哪个类,工厂方法把类的实例化推迟到子类中进行。
应用场景
创建对象需要大量重复的代码。
客户端不依赖产品类,实例如何被创建、实现等细节。
一个类通过其子类来指定创建哪个对象。
抽象工厂包含4个角色
抽象工厂(IFactory):工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(ConcreteFactory):实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且被应用程序调用以创建产品对象。
抽象产品(IProduct):工厂方法模式所创建的对象的超类型,是产品对象的共同父类或者共同拥有的接口。
具体产品(ConcreteProduct):这个角色实现了抽象产品角色所定义的接口。
工厂方法模式
优点:
灵活性增强,对于新产品的创建,只需要写一个相应的工厂类(GreenTeaFactory 、RedTeaFactory)。
典型的解耦框架。高层模块只需要知道产品的抽象类,无需关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则
缺点:
类的个数过多
增加了系统的抽象性和理解难度
抽象产品只能生产一种产品
package com.yab.fun;
public interface ITea{
//生产茶叶
public void teaName();
}
package com.yab.fun;
/**
* ConcreteProduct 简单工厂模式的创建目标
*/
public class GreenTea extends GreenTeaFactory implements ITea {
@Override
public void teaName() {
System.out.println("生产绿茶");
}
}
package com.yab.fun;
/**
* 具体产品ConcreteProduct:是简单工厂模式的创建目标。
*/
public class RedTea extends RedTeaFactory implements ITea {
@Override
public void teaName() {
System.out.println("生产红茶");
}
}
package com.yab.fun;
/**
* 抽象工厂(IFactory):工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
*/
public interface ITeaFactory {
com.yab.fun.ITea teaFactory();
}
package com.yab.fun;
/**
* 具体工厂(ConcreteFactory):实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且被应用程序调用以创建产品对象。
*/
public class GreenTeaFactory implements ITeaFactory {
@Override
public ITea teaFactory() {
return new GreenTea();
}
}
package com.yab.fun;
/**
* 具体工厂(ConcreteFactory):实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且被应用程序调用以创建产品对象。
*/
public class RedTeaFactory implements ITeaFactory {
@Override
public ITea teaFactory() {
return new RedTea();
}
}
package com.yab.fun;
public class TestFactoryFun extends RedTea {
/**
* 优点:
* 灵活性增强,对于新产品的创建,只需要写一个相应的工厂类(GreenTeaFactory 、RedTeaFactory)。
* 典型的解耦框架。高层模块只需要知道产品的抽象类,无需关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则
*
* 缺点:
* 类的个数过多
* 增加了系统的抽象性和理解难度
* 抽象产品只能生产一种产品
* @param args
*/
public static void main(String[] args) {
ITeaFactory iTeaFactory = new GreenTeaFactory();
iTeaFactory.teaFactory().teaName();
iTeaFactory = new RedTeaFactory();
iTeaFactory.teaFactory().teaName();
}
}
抽象工厂
抽象工厂模式适用于需要生成产品族的情景。抽象产品类内部提供了多个其他抽象产品,抽象工厂类定义了产品的创建接口,通过具体的工厂子类,就可以生产相应的产品族对象,供用户端使用。
抽象工厂包含4个角色
抽象工厂(IAbstractFactory):声明创建抽象产品对象的一个操作接口。
具体工厂(ConcreteFactory):实现创建具体产品对象的操作。
抽象产品(IAbstractProduct):为一类产品对象声明一个接口。
具体产品(ConcreteProduct):定义一个将被相应的具体工厂创建的产品对象,实现IAbstractProduct接口。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象工厂里加代码,又要在具体工厂的里面加代码,不符合开闭原则。
package com.yab.abstr;
public interface INote {
void edit();
}
package com.yab.abstr;
public interface IVideo {
void record();
}
package com.yab.abstr;
public class JavaNote implements INote {
@Override
public void edit() {
System.out.println("编写java笔记");
}
}
package com.yab.abstr;
public class JavaVideo implements IVideo {
@Override
public void record() {
System.out.println("录制java视频");
}
}
package com.yab.abstr;
public class PythonNote implements INote {
@Override
public void edit() {
System.out.println("编写python笔记");
}
}
package com.yab.abstr;
public class PythonVideo implements IVideo {
@Override
public void record() {
System.out.println("录制python视频");
}
}
package com.yab.abstr;
public abstract class CourseFactory {
public void init(){
System.out.println("初始化基础数据");
}
protected abstract INote createNote();
protected abstract IVideo createVideo();
}
package com.yab.abstr;
public class JavaCourseFactory extends CourseFactory {
@Override
protected INote createNote() {
return new JavaNote();
}
@Override
protected IVideo createVideo() {
return new JavaVideo();
}
}
package com.yab.abstr;
public class PythonCourseFactory extends CourseFactory {
@Override
protected INote createNote() {
return new PythonNote();
}
@Override
protected IVideo createVideo() {
return new PythonVideo();
}
}
package com.yab.abstr;
public class TestFactory {
public static void main(String[] args) {
CourseFactory courseFactory = new JavaCourseFactory();
courseFactory.createNote().edit();
courseFactory.createVideo().record();
}
}