知识点一:简单工厂模式
前言
1.概述
设计模式是针对某一类问题的最优解决方案,是从许多优秀的软件系统中总结出的。
Java中设计模式(java design patterns)通常有23种
(这次总结的设计模式多了一个简单工厂模式共24种)。这些模式大体上可以分成3类:
-
创建型模式:
创建型模式涉及对象的实例化,特点是不让用户代码依赖于对象的创建或排列方式,避免用户直接使用new创建对象。 主要有5种:
工厂方法模式
,抽象工厂模式
,单例模式
,建造者模式
,原型模式
。 -
结构型模式:
结构型模式涉及如何组合类和对象以形成更大的结构,和类有关的结构型模式涉及如何合理使用继承机制;和对象有关的结构型模式涉及如何合理的使用对象组合机制。 主要有7中:
适配器模式
,装饰器模式
,代理模式
,外观模式
,桥接模式
,组合模式
,享元模式
。 -
行为型模式:
行为型模式涉及怎样合理的设计对象之间的交互通信,以及怎样合理为对象分配职责,让设计富有弹性,易维护,易复用。 主要有11种:
策略模式
、模板方法模式
、观察者模式
、迭代子模式
、责任链模式
、命令模式
、备忘录模式
、状态模式
、访问者模式
、中介者模式
、解释器模式
。
2.设计模式遵循的原则:
-
开闭原则(Open Close Principle)
对扩展开放,对修改关闭
-
里氏代换原则(Liskov Substitution Principle)
只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
-
依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。
-
接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口来降低耦合度。
-
迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
-
合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。
接下来说第一个设计模式,简单工厂模式
一、概述
简单工厂模式是属于创建型模式
,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式
的一个特殊实现。简单地说就是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
二、优缺点及使用场景
优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了
高内聚
责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
这些缺点在工厂方法模式中得到了一定的克服。
使用场景
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
三、实现方式及模式中包含的角色和其职责
1、实现方式
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。 如图:
2、角色
- 工厂(Creator)角色
- 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象。
- 抽象(Product)角色
- 简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品(Concreate Product)角色
- 简单工厂模式所创建的具体实例对象。
四、在Java中的实现
1、创建抽象角色
Animal.java
/**
* @Description: 抽象类
* @Author: Ling.D.S
* @Date: Created in 2018/11/1 21:59
*/
public interface Animal {
public void get();
}
2、创建具体产品角色
Cat.java
/**
* @Description: 猫类
* @Author: Ling.D.S
* @Date: Created in 2018/11/1 21:16
*/
public class Cat implements Animal {
public void get(){
System.out.println("获得猫");
}
}
Dog.java
/**
* @Description: 狗类
* @Author: Ling.D.S
* @Date: Created in 2018/11/1 21:16
*/
public class Dog implements Animal {
public void get(){
System.out.println("获得狗");
}
}
3、创建工厂角色
AnimalFactory.java
/**
* @Description: 工厂类
* @Author: Ling.D.S
* @Date: Created in 2018/11/1 21:48
*/
public class AnimalFactory {
//注意要抛出三个异常,或者抛一个大的Exception
public static Animal getAnimal(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
/*if(type.equalsIgnoreCase("dog")){
return Dog.class.newInstance();
}else if(type.equalsIgnoreCase("cat")){
return Cat.class.newInstance();
}else{
System.out.println("没有该实例化类");
return null;
}*/
/* 优化 */
//通过类名获取class类
Class animal = Class.forName(type);
//通过class的newInstance方法实例化
return (Animal) animal.newInstance();
}
}
4、测试
/**
* @Description: 主方法
* @Author: Ling.D.S
* @Date: Created in 2018/11/1 21:16
*/
public class MainClass {
@Test
public void testStaticFactoryMethod(){
try {
//为防止误报ClassNotFoundException这里使用全限定路径指定
Animal cat = AnimalFactory.getAnimal("com.sdl.Cat");
Animal dog = AnimalFactory.getAnimal("com.sdl.Dog");
dog.get();
cat.get();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
结果如图:
转载请注明原地址,宋德凌的博客:http://CoderOfSong.github.io 谢谢!