Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于
所有文章 工具

Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于

工厂设计模式

阅读数:次 2018-10-23
字数统计: 2.7k字   |   阅读时长≈ 10分

六大设计原则

既然说到设计模式那就顺便回顾一下六大设计原则,六大设计原则是心法,二十三种设计模式是内功,下面只是简明的叙述了一下,后面还会有更详细的说明!
一 、 类单一职责原则: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操作的解耦合!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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)角色 工厂方法模式所创建的具体实例对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//抽象产品类
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开放封闭原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。 工厂方法模式退化后可以演变成简单工厂模式。

三、抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

有多少个产品等级结构,就会在工厂角色中发现多少个工厂方法。每一个产品等级结构中有多少个具体的产品,就有多少个产品族,也就会在工厂等级结构中发现多少个具体工厂。
在这里我使用水果举例子:

mark

模式中包含的角色及其职责

1.抽象工厂(Creator)角色 抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。
2.具体工厂( Concrete Creator)角色 具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。
3.抽象产品(Product)角色 抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
4.具体产品(Concrete Product)角色 抽象模式所创建的具体实例对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//水果抽象接口
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();
}
}

mark

这样比工厂方法模式更加抽象,抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例!

赏

谢谢你请我喝咖啡

支付宝
微信
  • 本文作者: Tim
  • 本文链接: https://zouchanglin.cn/2722994318.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!
  • 设计模式

扫一扫,分享到微信

软硬链接与Linux文件系统
系统IO接口
  1. 1. 六大设计原则
  2. 2. 工厂模式概述
    1. 2.1. 一、简单工厂模式
      1. 2.1.1. 模式中包含的角色及其职责:
      2. 2.1.2. 简单工厂模式的优缺点
    2. 2.2. 二、工厂方法模式
      1. 2.2.1. 模式中包含的角色及其职责:
      2. 2.2.2. 工厂方法模式和简单工厂模式比较:
    3. 2.3. 三、抽象工厂模式
      1. 2.3.1. 模式中包含的角色及其职责
© 2017-2021 Tim
本站总访问量次 | 本站访客数人
  • 所有文章
  • 工具

tag:

  • 生活
  • Android
  • 索引
  • MySQL
  • 组件通信
  • Nginx
  • JavaSE
  • JUC
  • JavaWeb
  • 模板引擎
  • 前端
  • Linux
  • 计算机网络
  • Docker
  • C/C++
  • JVM
  • 上传下载
  • JavaEE
  • SpringCloud
  • Golang
  • Gradle
  • 网络安全
  • 非对称加密
  • IDEA
  • SpringBoot
  • Jenkins
  • 字符串
  • vim
  • 存储
  • 文件下载
  • Mac
  • Windows
  • NIO
  • RPC
  • 集群
  • 微服务
  • SSH
  • 配置中心
  • XML
  • Chrome
  • 压力测试
  • Git
  • 博客
  • 概率论
  • 排序算法
  • 分布式
  • 异常处理
  • 文件系统
  • 哈希
  • openCV
  • 栈
  • 回溯
  • SpringCore
  • 流媒体
  • rtmp
  • 面向对象
  • Vue
  • ElementUI
  • 软件工程
  • 异步
  • 自定义UI
  • ORM框架
  • 模块化
  • 交互式
  • Jsoup
  • Http Client
  • LRUCache
  • RabbitMQ
  • 消息通信
  • 服务解耦
  • 负载均衡
  • 权限
  • 多线程
  • 单例模式
  • Protobuf
  • 序列化
  • Python
  • m3u8
  • 堆
  • 二叉树
  • 自定义View
  • 观察者模式
  • 设计模式
  • 线程池
  • 动态扩容
  • 高可用
  • GC
  • ffmpeg
  • SpringMVC
  • REST
  • Redis
  • 缓存中间件
  • UML
  • Maven
  • Netty
  • 高性能网络
  • IPC通信
  • IO
  • Stream
  • 发布订阅
  • SQLite
  • Hash
  • 集合框架
  • 链表
  • Lambda
  • 汇编语言
  • 组件化
  • Router
  • 开发工具

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia-plus根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 思维导图
  • PDF工具
  • 无损放大
  • 代码转图
  • HTTPS证书