工厂设计模式
六大设计原则
既然说到设计模式那就顺便回顾一下六大设计原则,六大设计原则是心法,二十三种设计模式是内功,下面只是简明的叙述了一下,后面还会有更详细的说明! 一 、 类单一职责原则:Single Responsibility Principle (SRP) 一个类只有一个引起这个类变化的原因。即一个类只完成一个功能,如果做不到一个类只完成一个功能,最少要保证一个方法只完成一个功能。
二、依赖倒置原则:Dependency Inversion Principle (DIP) 高层组件应该依赖抽象而不依赖具体,即面向接口编程,一般依赖的成员变量或者参数都应该是抽象的不应该是具体的。
三、里氏替换原则:Liskov Substitution Principle (LSP) 凡是父类出现的地方都可以用子类代替并且原功能没有发生变化,子类不应该覆盖父类的非抽象方法。
四、迪米特法则:Least Knowledge Principle (LKP) 一个类要尽量的封装自己,一个对象应该对其他对象有最少的了解,一个类只需要知道自己需要耦合或者调用类的public方法即可。
五、接口隔离原则:Interface Segregation Principle (ISP) 一个接口完成的功能尽可能的单一,不要让一个接口承担过多的责任。
六、开闭原则:The Open-Closed Principle (OCP) 对扩展开放,对修改闭合。
工厂模式概述
如何将实例化具体类的代码从客户端中抽离,或者封装起来?这就需要工厂模式: 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。工厂模式的核心作用就是把new操作解耦合!
一、简单工厂模式
简单工厂模式:专门定义一个类用来创建其它类的实例,被创建的实例通常都具有共同的父类。 Spring-BeanFactory就用到了简单工厂模式!
模式中包含的角色及其职责:
- 一个抽象产品类(接口)
- 多个具体产品类
- 一个工厂类(new 操作在此工厂中进行)客户端通过工厂类获取具体实例
以购买电脑为例子:这里我们相当于是创建生产电脑的工厂,客户需要购买什么样的电脑,只要输入类型编号就可以获取该电脑。将类的实例化交给工厂,易于new操作的解耦合!
import java.util.Scanner;
//定义的产品抽象类
abstract class Computer{
public abstract void fun();
}
//具体产品子类
class SufeBook extends Computer{
public void fun(){
System.out.println("This is SufeBook");
}
}
//具体产品子类
class MacBookPro extends Computer{
public void fun(){
System.out.println("This is MacBookPro");
}
}
//工厂类
class ComputerFactory{
private ComputerFactory(){}
public static Computer getComuter(String pcType){
Computer ret = null;
if(pcType.equals("mac")){
ret = new MacBookPro();
}else if(pcType.equals("sufe")){
ret = new SufeBook();
}
return ret;
}
}
public class Demo{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入笔记本");
Computer ret = ComputerFactory.getComuter(sc.next());
ret.fun();
}
}
简单工厂模式的优缺点
在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。 不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好,添加具体产品需要修改工厂违反OCP开放封闭原则!
二、工厂方法模式
定义一个用来创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类! Spring-FactoryBean就用到的是工厂方法模式! 工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
模式中包含的角色及其职责:
- 抽象工厂(Creator)角色 工厂方法模式的核心,任何工厂类都必须实现这个接口。
- 具体工厂( Concrete Creator)角色 具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
- 抽象(Product)角色 工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品(Concrete Product)角色 工厂方法模式所创建的具体实例对象
//抽象产品类
abstract class Computer{
public abstract void fun();
}
//具体产品类
class MacBookPro extends Computer {
public void fun(){
System.out.println("This is a MacBookPro!");
}
}
//具体产品类
class SufeBook extends Computer{
public void fun(){
System.out.println("This is a SufeBookPro!");
}
}
//抽象工厂接口
interface ComputerFactory {
Computer createComputer();
}
//实现工厂接口的具体类
class AppleFactory implements ComputerFactory{
public Computer createComputer(){
return new MacBookPro();
}
}
//实现工厂接口的具体类
class MicrosoftFactory implements ComputerFactory{
public Computer createComputer(){
return new SufeBook();
}
}
public class Demo{
public static void main(String[] args) {
ComputerFactory mf = new MicrosoftFactory();
Computer mfc = mf.createComputer();
mfc.fun();
ComputerFactory apple = new AppleFactory();
Computer mac = apple.createComputer();
mac.fun();
}
}
工厂方法模式和简单工厂模式比较:
工厂方法模式与简单工厂模式在结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。 工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。 当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对 象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了OCP开放封闭原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。 工厂方法模式退化后可以演变成简单工厂模式。
三、抽象工厂模式
抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。
有多少个产品等级结构,就会在工厂角色中发现多少个工厂方法。每一个产品等级结构中有多少个具体的产品,就有多少个产品族,也就会在工厂等级结构中发现多少个具体工厂。 在这里我使用水果举例子:
模式中包含的角色及其职责
1.抽象工厂(Creator)角色 抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。 2.具体工厂( Concrete Creator)角色 具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。 3.抽象产品(Product)角色 抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。 4.具体产品(Concrete Product)角色 抽象模式所创建的具体实例对象
//水果抽象接口
public interface Fruit {
void get();
}
//水果工厂接口
public interface FruitFactory {
//实例化Apple
public Fruit getApple();
//实例化Banana
public Fruit getBanana();
}
//苹果抽象类
public abstract class Apple implements Fruit {
@Override
public abstract void get();
}
//香蕉抽象类
public abstract class Banana implements Fruit {
@Override
public abstract void get();
}
//北方苹果具体类
public class NorthApple extends Apple {
public void get() {
System.out.println("NorthApple");
}
}
//南方香蕉具体类
public class NorthBanana extends Banana {
public void get() {
System.out.println("NorthBanana");
}
}
//新增加的温室苹果
public class GreenhouseApple extends Apple {
public void get() {
System.out.println("GreenhouseApple");
}
}
//新增的温室香蕉类
public class GreenhouseBanana extends Banana {
public void get() {
System.out.println("greenhouseBabanana");
}
}
//南方苹果具体类
public class SouthApple extends Apple {
public void get() {
System.out.println("SouthApple");
}
}
//北方香蕉具体类
public class NorthBanana extends Banana {
public void get() {
System.out.println("NorthBanana");
}
}
//北方水果工厂类
public class NorthFruitFactory implements FruitFactory {
public Fruit getApple() {
return new NorthApple();
}
public Fruit getBanana() {
return new NorthBanana();
}
}
//南方水果工厂类
public class SouthFruitFactory implements FruitFactory {
public Fruit getApple() {
return new SouthApple();
}
public Fruit getBanana() {
return new SouthBanana();
}
}
//温室具体工厂类
public class GreenhouseFruitFactory implements FruitFactory {
//返回GreenhouseApple
public Fruit getApple() {
return new GreenhouseApple();
}
//返回GreenhouseBanana
public Fruit getBanana() {
return new GreenhouseBanana();
}
}
public class Demo{
public static void main(String[] args) {
FruitFactory northfruitFactory = new NorthFruitFactory();
Fruit apple = northfruitFactory.getApple();
Fruit banana = northfruitFactory.getBanana();
apple.get();
banana.get();
System.out.println("---------------------------");
FruitFactory southFruitFactory = new SouthFruitFactory();
Fruit apple2 = southFruitFactory.getApple();
Fruit banana2 = southFruitFactory.getBanana();
apple2.get();
banana2.get();
System.out.println("--------------------------");
GreenhouseFruitFactory greenhouseFruitFactory = new GreenhouseFruitFactory();
Fruit apple3 = greenhouseFruitFactory.getApple();
Fruit banana3 = greenhouseFruitFactory.getBanana();
apple3.get();
banana3.get();
}
}
这样比工厂方法模式更加抽象,抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例!