JAVA常用设计模式(2)工厂模式
来源:互联网 发布:世界十大灾难片 知乎 编辑:程序博客网 时间:2024/05/30 12:30
1. 引入
工厂模式根据抽象程度的不同分为三种:简单工厂模式(也叫静态工厂模式)、工厂方法模式、以及抽象工厂模式。
工厂模式的主要优点有:
- 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
- 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
- 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
2. 简单工厂模式
简单工厂模式中定义一个抽象类,抽象类中声明公共的特征及属性,抽象子类继承自抽象类,去实现具体的操作。工厂类根据外界需求,在工厂类中创建对应的抽象子类实例并传给外界,而对象的创建是由外界决定的。外界只需要知道抽象子类对应的参数即可,而不需要知道抽象子类的创建过程,在外界使用时甚至不用引入抽象子类。
简单工厂模式将抽象子类的创建,和关于抽象子类相关的业务逻辑分离,降低对象间的耦合度。由于工厂类只是为外界创建对象,所以并不需要实例化工厂类对象,只需要为外界提供类方法即可。外界需要什么类型的抽象子类,只需要传递对应的参数即可。外界不需要知道具体的抽象子类,只需要使用抽象类即可。
简单工厂模式主要包含三部分:
- 工厂类:根据外界的需求,决定创建并返回哪个具体的抽象子类。
- 抽象类:定义抽象子类所需的属性和方法,子类通过继承自抽象类获得这些方法。
- 抽象子类:继承自抽象类,是具体操作的实现者,根据需求重写父类继承过来的方法。
代码示例(这里使用接口的形式,关于抽象类和接口的选择可以根据具体情况而定,抽像类更侧重于属性的继承,接口更侧重于实现相同的方法,因为java的单继承问题,所以尽量多使用接口,这更利于设计中的组合原则。):
抽象类和接口的区别(语法区别):
- 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
// 动物接口public interface IAnimal { //品种 public void kind();}// 猫类public class Cat implements IAnimal { @Override public void kind() { System.out.println("I am cat!"); }}//狗类public class Dog implements IAnimal { @Override public void kind() { System.out.println("I am dog!"); }}// 动物工厂类public class AnimalFactory { /** * 这里采用反射的机制 * @param clz * @return */ public static <T extends IAnimal> chooseAnimal(Class<T> clz) { try { return (IAnimal) Class.forName(clz.getName()).newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }}//主类public class Main { public static void main(String[] args) { IAnimal animal = AnimalFactory.chooseAnimal("Cat"); if (null != animal) { animal.kind(); } else { System.out.println("没有此动物!"); } }}
3. 工厂方法模式
工厂方法模式和简单工厂模式十分类似,大致结构是基本类似的。不同在于工厂方法模式对工厂类进行了进一步的抽象,将之前的一个工厂类抽象成了抽象工厂和工厂子类,抽象工厂定义一个创建抽象子类的接口,抽象工厂的子类实现这些接口并决定实例化哪个抽象子类。工厂子类决定着创建哪个抽象子类,外界决定着创建哪种工厂子类,抽象子类和工厂子类是一一对应的。
在工厂方法模式中,和简单工厂模式一样,对外隐藏了抽象子类的创建过程,外界只需要关心工厂类即可,负责实例化的工厂子类决定着最后的结果。
工厂方法模式主要包含四部分:
- 工厂抽象类:定义创建抽象子类的接口,通过接口返回具体的抽象子类。
- 工厂子类:继承自工厂抽象类,并重写父类的方法来创建对应的抽象子类。
- 抽象类:定义抽象子类所需的属性和方法,子类通过继承自抽象类获得这些方法。
- 抽象子类:继承自抽象类,实现具体的操作。
代码示例:
//产品类public abstract class Iphone { public abstract void camera(); public abstract void screen();}//具体的产品类 Iphone7 public class Iphone7 extends Iphone { @Override public void camera() { Log.e("Iphone7", "Iphone7的单摄"); } @Override public void screen() { Log.e("Iphone7", "Iphone7的4.7寸屏幕"); }}//具体的产品类 Iphone7Pluspublic class Iphone7Plus extends Iphone { @Override public void camera() { Log.e("Iphone7Plus", "Iphone7Plus的双摄"); } @Override public void screen() { Log.e("Iphone7Plus", "Iphone7Plus的5.5寸屏幕"); }}//抽象的工厂类:public abstract class IphoneFactory { public abstract Iphone createPhone();}//具体的工厂类:public class Iphone7Factory extends IphoneFactory { @Override public Iphone createPhone() { return new Iphone7(); }}public class Iphone7PlusFactory extends IphoneFactory { @Override public Iphone createPhone() { return new Iphone7Plus(); }}// 测试类public class Client { public static void test() { IphoneFactory factory = new Iphone7Factory(); Iphone7 iphone7 = factory.createPhone(); iphone7.camera(); iphone7.screen(); IphoneFactory factory1 = new Iphone7PlusFactory(); Iphone7Plus iphone7Plus= factory1.createPhone(); iphone7Plus.camera(); iphone7Plus.screen(); }}
4. 抽象工厂模式
抽象工厂模式和工厂方法模式很相似,但是抽象工厂模式将抽象发挥的更加极致,是三种工厂模式中最抽象的一种设计模式。抽象工厂模式,也叫做Kit模式,提供了创建一系列相关抽象子类的接口,而无需指定它们具体的类型。
抽象工厂模式中定义了抽象工厂类,抽象工厂类中定义了每个系列的抽象子类创建所需的方法,这些方法对应着不同类型的抽象子类实例化过程。每个工厂子类都对应着一个系列,工厂子类通过重写这些方法来实例化当前系列的抽象子类。
工厂方法模式中抽象子类都是基于同一个抽象类的,是同一个类型的抽象子类,例如加、减、乘、除都属于运算类型。而抽象工厂模式可能会有多个类型的抽象类,抽象子类分别继承自对应类型的抽象类,相同类型的抽象子类都是属于不同系列的。
抽象工厂模式包含四部分:
- 抽象工厂类:定义创建抽象子类的具体行为,根据系列中不同类型的抽象子类可能会有多种行为。
- 工厂子类:继承自抽象工厂类,根据当前抽象子类对应的系列,重写父类定义的对应行为。对应的抽象子类系列不同,行为的实现方式也不同。
- 抽象类:定义当前类型抽象子类的操作,子类继承父类完成具体的操作。在抽象工厂模式中,可能会有多种抽象类的定义。
- 抽象子类:根据当前类型继承自对应的抽象类,并根据系列的不同重写抽象类定义的实现
代码示例:
// 产品 Plant接口 public interface Plant { }//具体产品PlantA,PlantB public class PlantA implements Plant { public PlantA () { System.out.println("create PlantA !"); } public void doSomething() { System.out.println(" PlantA do something ..."); } } public class PlantB implements Plant { public PlantB () { System.out.println("create PlantB !"); } public void doSomething() { System.out.println(" PlantB do something ..."); } } //产品Fruit接口 public interface Fruit { } //具体产品FruitA,FruitB public class FruitA implements Fruit { public FruitA() { System.out.println("create FruitA !"); } public void doSomething() { System.out.println(" FruitA do something ..."); } } public class FruitB implements Fruit { public FruitB() { System.out.println("create FruitB !"); } public void doSomething() { System.out.println(" FruitB do something ..."); } } //抽象工厂方法 public interface AbstractFactory { public Plant createPlant(); public Fruit createFruit(); } //具体工厂方法 public class FactoryA implements AbstractFactory { public Plant createPlant() { return new PlantA(); } public Fruit createFruit() { return new FruitA(); } } public class FactoryB implements AbstractFactory { public Plant createPlant() { return new PlantB(); } public Fruit createFruit() { return new FruitB(); } }// 主类调用测试public class Main { public static void main(String[] args) { AbstractFactory instance = new FactoryA(); instance.createPlant(); }}
5. 总结
1.什么时候会去用工厂模式?(简单工厂,工厂方法,抽象工厂)。
- 为了不再需要直接创建对象,降低代码耦合度。对于创建多种具有同一系列行为的物体,使用工厂方法。对于产品族使用抽象工厂。
2.简单工厂的缺点。
- 简单工厂主要违反了开闭原则:对扩展开放,对修改关闭。添加一种对象,就要去修改简单工厂中的获取对象方法。
- JAVA常用设计模式(2)工厂模式
- JAVA常用设计模式(2)工厂模式
- java 常用设计模式(工厂设计模式)
- 设计模式-java工厂模式2(抽象工厂模式)
- Java 常用的设计模式-工厂模式
- 常用Java设计模式系列(5)- 简单工厂、工厂方法模式和抽象工厂模式
- java设计模式(2)--工厂模式
- Java常用设计模式之工厂模式(Factory)
- Java常用设计模式详解(一)---工厂模式
- Java常用设计模式详解(一)---工厂模式
- Java常用设计模式(一)——工厂模式
- Java技术常用设计模式(四)--- 工厂模式
- Java设计模式--工厂模式(简单工厂+工厂方法)
- Java设计模式-工厂模式(简单工厂+工厂方法)
- Java设计模式:工厂模式(一)简单工厂模式
- Java设计模式-工厂模式(1)简单工厂模式
- java设计模式2 工厂
- Java(工厂设计模式)
- js,jQuery初学易出现问题
- PCB拼版设计
- 一个简单的python3爬虫
- robots.txt的作用
- Unreal Engine 4 C++ UCLASS构造函数易出错分析
- JAVA常用设计模式(2)工厂模式
- Adaboost 算法的原理与推导
- tcpdump
- Android Data Binding 高级用法
- 第八周实践都要学C
- vim delete
- Ubuntu 18.10可能取消对 32 位的支持!
- Java 实现最优路径查找算法(伪Leetcode路径查找算法)
- JZOJ 4822. 【NOIP2016提高A组集训第1场10.29】完美标号