简单工厂模式
简单工厂模式不属于23种GOF设计模式,简单工厂模式是将在客户端创建产品的方式抽取到了工厂中进行创建,例如,电子产品店铺是一个类,卖手机和电脑,并且手机和电脑是在他们店里的,如果要卖平板则需要进货,现在将电脑,平板都通过工厂直销,工厂不仅负责造,还负责送货,这样店铺里客人买了什么工厂就造什么,如果需要加入平板则在工厂中设置对应的产品即可,不然如果多家店铺的话所有店铺都需要引进平板。最初产品和店铺的耦合转移到了工厂中。简单工厂模式并不符合开闭原则
简单工厂模式主要角色如下:
抽象产品:定义了产品的规范,描述了产品的主要特性和功能
具体产品:实现或继承抽象产品的子类
具体工厂:提供了创建产品的方法,调用者通过该方法来创建产品
案例实现
工厂根据需求的不同创建不同的产品,代码如下:
抽象产品接口,定义产品的相关规范
public interface AbstractProduct { void show(); }
电脑产品
public class Computer implements AbstractProduct{ @Override public void show() { System.out.println("电脑产品"); } }
手机产品
public class Phone implements AbstractProduct{ @Override public void show() { System.out.println("手机产品"); } }
具体工厂
public class SimpleFactory { //还有一种工厂方式是将创建产品的方法使用static关键字进行修饰,称为静态工厂 AbstractProduct createProduct(String productName){ if(productName.equals("computer")){ return new Computer(); } else if(productName.equals("phone")){ return new Phone(); } else{ return null; } } }
测试类,传入手机参数构造手机产品
public class Test { public static void main(String[] args) { SimpleFactory factory=new SimpleFactory(); AbstractProduct product=factory.createProduct("phone"); product.show(); } }
简单工厂模式不符合开闭原则,当需要添加其他电子产品时,需要修改原有的工厂类的方法还有一种实现方式时通过静态工厂方法结合配置文件实现开闭原则,工厂类改造代码如下:
public class SimpleStaticFactory { private static Map<String, AbstractProduct> productMap=new HashMap<>(); //通过静态代码块加载配置文件中的配置,通过配置文件中配置的类的全类名使用反射机制构造产品实例对象并放入productMap中 static{ Properties properties=new Properties(); Class<SimpleStaticFactory> current=SimpleStaticFactory.class; //获取配置文件 try(InputStream in=current.getClassLoader().getResourceAsStream("simpleStaticFactory.properties")){ properties.load(in); //获取配置文件中的所有建 Set<Object> keys=properties.keySet(); for(Object key:keys){ String k=(String) key; //根据建获取到配置文件中定义的全限定类名 String classPath=(String) properties.get(k); //利用反射机制构建抽象产品对象,存入容器中 Class<?> cls=Class.forName(classPath); Constructor<?> con=cls.getConstructor(); AbstractProduct product=(AbstractProduct)con.newInstance(); productMap.put(k,product); } }catch(Exception e){ e.printStackTrace(); } } public static AbstractProduct getInstance(String productName){ return productMap.get(productName); } }
配置文件simpleStaticFactory.properties内容如下:
computer=factory.simple_factory.Computer phone=factory.simple_factory.Phone
测试类
public class Test { public static void main(String[] args) { AbstractProduct product=SimpleStaticFactory.getInstance("phone"); product.show(); } }
现在需要新增其他产品也不需要改动配置类了,直接在配置文件中新增即可
工厂方法模式
工厂方法模式完全符合开闭原则。工厂方法模式是定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
工厂方法模式主要角色:
抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
具体工厂:主要使实现抽象工厂中的抽象方法,完成具体的产品的创建
抽象产品:定义了产品的规范,描述了产品的主要特征和功能
具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,和具体工厂之间是一对一的关系
案例实现
市面上有很多的电子产品,例如手机,电脑。他们都有不同的电子厂进行生产,例如电脑生产电子厂,手机生产电子厂。代码实现如下:
定义抽象电子厂
public interface AbstractFactory { AbstractProduct createProduct(); }
定义抽象电子产品
public interface AbstractProduct { void show(); }
定义电脑产品类
public class Computer implements AbstractProduct { @Override public void show() { System.out.println("使用电脑产品"); } }
定义生产电脑的电子厂类
public class ComputerFactory implements AbstractFactory { @Override public AbstractProduct createProduct() { return new Computer(); } }
定义手机产品类
public class Phone implements AbstractProduct { @Override public void show() { System.out.println("使用手机产品"); } }
定义生产手机的电子厂类
public class PhoneFactory implements AbstractFactory { @Override public AbstractProduct createProduct() { return new Phone(); } }
测试代码
public class Test { public static void main(String[] args) { //调用电脑生产电子厂 AbstractFactory factory=new ComputerFactory(); //创建电脑产品 AbstractProduct product=factory.createProduct(); product.show(); } }
工厂方法模式类图如下:
工厂方法模式优缺点
优点:
1.用户只需要知道具体工厂的名称就可得到想要的产品,无需知道产品的具体创建过程
2.在系统增加新的产品是只需要添加具体的产品和对应的具体工厂类,无需对原工厂进行任何修改,满足开闭原则
缺点:
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度
抽象工厂模式
抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无需指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂可生产多个等级的产品
抽象工厂模式的主要角色如下:
抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
抽象产品:定义了产品的规范,描述了产品的主要特征和功能,抽象工厂模式有多个抽象产品
具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它和具体工厂是多对一关系
案例实现
市面上有很多的电子产品,例如手机,电脑。电子产品之间又有很多的厂商可以进行生产,例如手机厂商有苹果和华为,电脑厂商同样有苹果和华为。由此可见,苹果可以生产苹果电脑和手机,华为可以生产华为电脑和手机,代码实现如下:
抽象工厂接口,定义了工厂能够创建的抽象产品以及方法
public interface AbstractFactory { AbstractPhone createPhone(); AbstractComputer createComputer(); }
抽象手机产品,定义了手机的规范
public interface AbstractPhone { void call(); }
抽象电脑产品,定义了电脑的规范
public interface AbstractComputer { void run(); }
定义华为工厂,能够生产华为手机和华为电脑
public class HuaFactory implements AbstractFactory { @Override public AbstractPhone createPhone() { return new HuaPhone(); } @Override public AbstractComputer createComputer() { return new HuaComputer(); } }
定义华为电脑,华为电脑需要遵循市场的电脑规范,故实现电脑规范接口
public class HuaComputer implements AbstractComputer { @Override public void run() { System.out.println("使用华为电脑运行程序"); } }
定义华为手机,华为手机需要遵循市场的手机规范,故实现手机规范接口
public class HuaPhone implements AbstractPhone { @Override public void call() { System.out.println("使用华为手机拨打电话"); } }
定义苹果工厂,能够生产苹果手机和电脑
public class AppleFactory implements AbstractFactory { @Override public AbstractPhone createPhone() { return new ApplePhone(); } @Override public AbstractComputer createComputer() { return new AppleComputer(); } }
定义苹果电脑,苹果电脑需要遵循市场的电脑规范,故实现电脑规范接口
public class AppleComputer implements AbstractComputer { @Override public void run() { System.out.println("使用苹果电脑运行程序"); } }
定义华为手机,华为手机需要遵循市场的手机规范,故实现手机规范接口
public class ApplePhone implements AbstractPhone { @Override public void call() { System.out.println("使用苹果手机拨打电话"); } }
测试,通过苹果工厂构建苹果的手机和电脑
public class Test { public static void main(String[] args) { AbstractFactory factory=new AppleFactory(); AbstractPhone phone=factory.createPhone(); AbstractComputer computer=factory.createComputer(); phone.call(); computer.run(); } }
抽象工厂模式优缺点
优点:当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
缺点:当产品族中需要增加一个新的产品时,所有工厂类都需要修改,例如电子厂商不仅要生产电脑和手机,同时还要生产平板,那么上述代码的华为工厂和苹果工厂就需要增加生产平板的方法。
抽象工厂模式使用场景
当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机,洗衣机,空调等
系统中有多个产品族,但每次只使用其中的某一族产品,如有人喜欢某一个品牌的衣服和鞋子
系统中提供了产品的类库,且所有产品接口相同,客户端不依赖产品实例的创建细节和内部结构,如输入法换皮肤,一整套一起换。生产不同的操作系统的程序。
希望这篇文章对您有帮助,同时也希望您在闲暇之余能够帮忙使用微信扫一下下面的小程序二维码帮忙助力一下小程序的访问量,谢谢