java工厂类设计模式,Java的工厂模式
00-1010工厂模式1。简单工厂1.1结构1.2实现1.3优缺点1.4扩展2。工厂方法2.1结构2.2实现2.3优缺点3。抽象工厂3.1结构3.2实现3.3优缺点4。模式扩展4.1实现
00-1010对象在Java应用中无处不在,所有这些对象都需要创建。如果新对象是直接创建的,那么如果我们想要替换对象,新对象的所有位置都需要改变。违背了软件设计原理中的开闭原则。如果使用工厂生产对象,只需要关注工厂中对象的变化,从而达到与对象脱钩的目的。工厂模式最大的特点就是解耦。
补充:
开放封闭原则:对扩展开放,对修改封闭。当程序需要扩展时,不能通过修改原代码来达到热插拔的效果。是为了让程序具有可扩展性,易于维护和升级。
目录
00-1010抽象产品:定义产品规格,描述产品的主要特性和功能。产品:实现或继承抽象产品的子类。具体工厂:提供创建产品的方法,调用者通过该方法创建产品。
00-1010以点咖啡为例3360
抽象咖啡类
公共抽象类Coffee {/* * * Get Coffee type * @ return */public abstract string GetName();/* * *加糖*/public void add sugar(){ system . out . println(加糖);}/* * *加奶*/public void加奶(){system.out.println(加奶);}}美国咖啡
Class American coffee扩展coffee { @ override public string getname(){ return American coffee ;}}拿铁咖啡
Public Latte Coffee扩展Coffee { @ override public string getname(){ return Latte ;}}咖啡工厂类
public class Coffee factory { public Coffee create Coffee(String类型){ Coffee coffee=nullif(美国人)。equals(type)){ coffee=new American coffee();}else if(latten 。equals(type)){ coffee=new latte coffee();}else{ throw new RuntimeException(没有这种咖啡);}回咖啡;}}咖啡店类
public class Coffee store { public Coffee order Coffee(String type){ Coffee factory factory=new Coffee factory();//调用咖啡制作方法coffee coffee=factory . create coffee(type);coffee . addmilk();coffee . add sugar();回咖啡;}}测试类
public class Test { public static void main(String[]args){ coffee store coffee store=new coffee store();咖啡coffee=coffee store . order coffee( latten );system . out . println(coffee . getname());}}类图
咖啡工厂负责生产咖啡(具体工作
厂),咖啡店通过咖啡工厂选取咖啡
其实简单工厂是大家在实际写代码的时候经常用到的,虽然简单工厂实现了咖啡店与咖啡的耦合,但是可以明显看到咖啡与咖啡工厂又耦合起来了,后期如果增加咖啡的新品种,我们需要修改咖啡工厂的代码,这又违背了“开闭原则”。
注意:
简单工厂和不使用工厂是有很大区别的,如果咖啡店有多个,不使用工厂如果遇到新增咖啡需要修改所有咖啡店,但是使用工厂只需要修改咖啡工厂,类似于将所有咖啡店抽取出一个抽象的咖啡店。
1.3优缺点
优点:
封装了创建对象的过程,可以通过参数直接获取对象,把对象的创建和业务逻辑层分开,这样可以避免之后修改客户代码,如果需要实现新产品直接修改工厂类,更容易扩展。
缺点:
增加新产品时还需要修改工厂类的代码,违背了“开闭原则”。
1.4扩展
静态工厂,将工厂类中创建对象的功能定义为静态的,这样不需要再创建工厂类,直接通过类名调用静态方法,类似于工具类
public class CoffeeFactory { //静态方法 public static Coffee createCoffee(String type){ Coffee coffee = null; if("american".equals(type)){ coffee = new AmericanCoffee(); }else if("latten".equals(type)){ coffee = new LatteCoffee(); }else{ throw new RuntimeException("没有此类型的咖啡"); } return coffee; }}
2.工厂方法
对工厂进行抽象,每一种产品对应一个具体工厂,新增产品只需要再新增对应的具体工厂,符合”开闭原则“
2.1结构
抽象工厂: 提供创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品 具体工厂: 主要是实现抽象工厂中的抽象方法,完成具体产品的创建 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能 具体产品: 实现抽象产品所定义的接口,由具体工厂来创建,与具体工厂之间一一对应
2.2实现
抽象咖啡类和具体咖啡类不变
咖啡工厂(抽象工厂)
public interface CoffeeFactory { /** * 创建咖啡 * @return */ Coffee createCoffee();}
美式咖啡工厂(具体工厂)
public class AmericanCoffeeFactory implements CoffeeFactory{ //美式咖啡工厂对象,专门生产美式咖啡 @Override public Coffee createCoffee() { return new AmericanCoffee(); }}
拿铁咖啡工厂(具体工厂)
public class LatteCoffeeFactory implements CoffeeFactory{ //拿铁咖啡工厂对象,专门生产拿铁咖啡 @Override public Coffee createCoffee() { return new LatteCoffee(); }}
咖啡店
public class CoffeeStore { private CoffeeFactory factory; public void setFactory(CoffeeFactory factory) { this.factory = factory; } /** * 点咖啡 */ public Coffee orderCoffee() { Coffee coffee = factory.createCoffee(); coffee.addSugar(); coffee.addMilk(); return coffee; }}
测试类
public class Test { public static void main(String[] args) { //创建咖啡店对象 CoffeeStore coffeeStore = new CoffeeStore(); //创建工厂对象 CoffeeFactory factory = new AmericanCoffeeFactory(); coffeeStore.setFactory(factory); //点咖啡 Coffee coffee = coffeeStore.orderCoffee(); System.out.println(coffee.getName()); }}
类图
我们只需要知道所点咖啡具体对应的工厂对象,通过咖啡店调用对应的工厂,由工厂创建咖啡对象实现点咖啡的过程
2.3优缺点
优点:
用户只需要知道具体工厂就可以获得所需产品,无需知道产品的具体创建过程 在系统新增产品时只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行修改符合“开闭原则”缺点:
每增加一个产品就要增加一个对应的具体工厂类,增加的系统的复杂性。如果具体产品种类过多,那么大量的工厂类不仅难以管理,而且也会造成程序中创建的对象过多,严重影响内存性能
3.抽象工厂
3.1结构
抽象工厂: 提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品 具体工厂: 主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品 具体产品: 实现抽象产品所定义的接口,由具体工厂来创建,与具体工厂是多对一关系
3.2实现
咖啡抽象类
public abstract class Coffee { /** * 获取咖啡类型 * @return */ public abstract String getName(); /** *加糖 */ public void addSugar(){ System.out.println("加糖"); } /** *加奶 */ public void addMilk(){ System.out.println("加奶"); }}
美式咖啡类
public class AmericanCoffee extends Coffee{@Override public String getName(){ return "美式咖啡"; }}
拿铁咖啡类
public class LatteCoffee extends Coffee { @Override public String getName(){ return "拿铁咖啡"; }}
甜品抽象类
public abstract class Dessert { //甜品抽象类 public abstract void show();}
抹茶慕斯类
public class MatchaMousse extends Dessert{//抹茶慕斯类 @Override public void show() { System.out.println("抹茶慕斯"); }}
提拉米苏类
public class Tiramisu extends Dessert{ //提拉米苏类 @Override public void show() { System.out.println("提拉米苏"); }}
甜品工厂
public interface DessertFactory { /** * 生产咖啡 * @return */ Coffee createCoffee(); /** * 生产甜品 * @return */ Dessert createDessert();}
美式风味甜品工厂类
public class AmericanDessertFactory implements DessertFactory{ /** *美式风味甜品工厂 * 可以生产美式咖啡和抹茶慕斯 */ @Override public Coffee createCoffee() { return new AmericanCoffee(); } @Override public Dessert createDessert() { return new MatchaMousse(); }}
意大利风味甜品工厂类
public class ItalyDessertFactory implements DessertFactory { /** *意大利风味甜品工厂 * 可以生产拿铁咖啡和提拉米苏 */ @Override public Coffee createCoffee() { return new LatteCoffee(); } @Override public Dessert createDessert() { return new Tiramisu(); }}
测试类
public class Test { public static void main(String[] args) { //ItalyDessertFactory factory = new ItalyDessertFactory(); AmericanDessertFactory factory = new AmericanDessertFactory(); Coffee coffee = factory.createCoffee() Dessert dessert = factory.createDessert(); System.out.println(coffee.getName()); dessert.show(); }}
类图
由类图可见,抽象工厂不再是一个具体工厂对应一个产品,而是一个具体工厂对应一个产品族。如果需要增加一个产品族只需加对应的工厂类,符合”开闭原则“
3.3优缺点
优点:
在工厂方法的基础上减少了部分对象的创建,适合于每次只使用同一产品族的对象这类应用场景
缺点:
当产品族中需要增加一个产品时,所有工厂都要修改
4.模式扩展
配置文件+简单工厂
通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件的全类名,通过反射创建对象并存储在容器中,如果需要直接从容器中获取(Spring IOC原理)
4.1实现
1.定义配置文件
american = com.xue.config_factory.AmericanCoffeelatten = com.xue.config_factory.LatteCoffee
2.改进工厂类
public class CoffeeFactory { /** * 加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储 */ //1.定义容器对象存储咖啡对象 private static HashMap<String, Coffee> map = new HashMap<>(); //2.加载配置文件 static { //创建 Properties对象 Properties properties = new Properties(); //调用properties对象中的load方法进行配置文件的加载 InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties"); try { properties.load(is); //从properties中获取全类名 Set<Object> keys = properties.keySet(); for (Object key : keys) { String className = properties.getProperty((String) key); //通过反射创建对象 Class class1 = Class.forName(className); Coffee coffee = (Coffee) class1.newInstance(); //将名称和对象存储在容器中 map.put((String) key,coffee); } } catch (Exception e) { e.printStackTrace(); } } //根据名称获取对象 public static Coffee createCoffee(String name) { return map.get(name); }}
静态成员变量用来存储创建的对象(键存储的是名称,值存储的是对应的对象),而读取配置文件和创建对象写在静态代码块中只需要执行一次
测试类
public class Test { public static void main(String[] args) { Coffee coffee = CoffeeFactory.createCoffee("american"); System.out.println(coffee.getName()); System.out.println("------------"); Coffee latten = CoffeeFactory.createCoffee("latten"); System.out.println(latten.getName()); }}
成功!!!
以上就是Java设计模式——工厂模式的介绍及四种实现方式 往期链接:单例模式
到此这篇关于Java超详细讲解设计模式之一的工厂模式的文章就介绍到这了,更多相关Java 工厂模式内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。