Fork me on GitHub

设计模式

十月间断的学了一些设计模式。这是个长久的课程,还没有学会怎么实际运用到项目中。

跟随着视频来学

为什么学习设计模式?

为了让程序具有更好的代码重用性,可读性,可扩展性,可靠性,使程序呈现高内聚,低耦合的特性。

什么时候用到设计模式?

面向对象(oo)=> 功能模块[设计模式 + 算法(数据结构)] => 框架[ 多种设计模式 ] => 架构[ 服务器集群 ]

学习步骤

应用场景 –> 设计模式 –> 剖析原理 –> 分析实现步骤(图解,类图) –> 代码实现 –> 框架或项目源码分析的步骤讲解

设计模式的七大原则

设计模式为什么这样设计的原则。

字符流会查码表,字节流不查码表

编码:字符—>码表—>数字

解码:数字—>码表—>字符

Reader默认查询的码表是与操作系统一致的码表,操作系统是中文的,所以reader使用GBK码表

java查的是unicode的码表

1. 单一职责原则

一个类只负责一个职责。

2. 接口隔离原则

使用多个单独的接口。

3. 依赖倒转原则

其核心是面向接口编程(即抽象类)。

4. 迪米特法则(最少知道原则)

体现了封装的思想。可以适当违反。

5. 开闭原则OCP

对扩展开放,对修改关闭。

6. 里氏替换原则

oo中继承的思考。

所有引用基类的地方必须能透明的使用其子类的对象。

使用继承时尽量不要重写父类的方法。

创建一个更加基础的类。使用依赖,聚合,组合的关系。

7. 合成复用原则

尽量使用合成聚合的方式,而不是使用继承。

UML语言介绍

统一建模语言。

类图-依赖关系(Dependence)只要在类中用到了对方,他们就存在依赖关系。

类图-泛化关系(generalization),就是继承关系,是依赖关系的特例。

类图-实现关系(Implement),是依赖关系的特例

1
2
3
4
5
6
public interface PersonService{
public void delete(Interger id);
}
public class PersonServiceBean implements PersonService{
public void delete(Interger id){}
}

类图-关联关系(Association)

类与类之间的联系,是依赖关系的特例。有单向和双向关系。

类图-聚合关系(Aggregation) 整体与部分的关系,整体与部分可以分开。比如Person和IDCard。聚合式关联关系的特例。

类图-组合关系(Composition)也是整体与部分的关系,但是整体与部分不可以分开。例如Person和head。同生共死的关系。

1
2
3
4
5
6
public class Person{
private IDCard card;
private Head head = new head();
}
public class IDCard{}
public class Head{}

创建型模式

1. 单例模式

主要步骤:

1) 构造器私有化 (防止 new )

2) 类的内部创建对象

3) 向外暴露一个静态的公共方法

饿汉式

1
2
3
4
5
6
7
8
9
10
11
12
class Singleton{
//构造器私有化
new private Singleton(){

}
//本类内部创建对象实例。
private final static Singleton instance = new Singleton();
//提供一公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instantce;
}
}

优缺点:写法简单,在类装载的时候完成实例化,避免了线程同步问题,没有达到懒加载的效果。

可用,但会造成内存的浪费。

双重检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Singleton{
private static volatile Singleton instance;//volatile可以实现立刻写到内存中
//构造器私有化
private Singleton(){}

public static synchronized Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}

Double-Check是多线程开发中常使用的。线程安全,延迟加载,效率较高。

静态内部类

1
2
3
4
5
6
7
8
9
10
11
12
class Singleton{
private static volatile Singleton instance;
private Singleton(){}
//写一静态内部类
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//提供一静态的公有方法,直接返回 SingletonInstance.INSTANCE。
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}

静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在需要实例化时,调用 getInstance 方法,才会装载 SingletonInstance 类,从而完成 Singleton 的实例化。避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。推荐使用。

枚举法

1
2
3
4
5
6
enum Singleton{
INSTANCE;
public void sayOK(){
System.out.println("ok");
}
}

借助 JDK1.5 中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。这种方式是 \Effective** \Java** 作者 \Josh** \Bloch** 提倡的方式.推荐使用

2. 简单工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
class FoodFactory{
public static Food getFood(int n){
Food food = null;
switch(n){
case 1:
food = new Hamburger();
break;
case 2:
food = new RiceNoodle();
break;
}
return food;
}
}
...

服务器修改了具体产品的类名后,客户端不知道。

工厂的实现不易于扩展,违反了ocp原则,故引入了工厂方法模式。

3. 工厂方法模式

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
interface food{
void eat();
}

class Hamburger implements Food{
public void eat(){
System.out.println("吃汉堡!");
}
}
class RiceNoodle implements Food{
public void eat(){
System.out.println("吃米线!");
}
}
//食物工厂
interface FoodFactory{
public Food getFood(){}
}

class HamburgerFactory implements FoodFactory{
public Food getFood(){
return new Hamburger();
}
}
class RiceNoodleFactory implements FoodFactory{
public Food getFood(){
return new RiceNoodle();
}
}

public static void main(){
FoodFactory ff = new HamburgerFactory();
Food food = ff.getFood();
food.eat();
}

工厂的名字是视为接口的,是趋向稳定的。

但是当种类很多时,会造成类爆炸式增长,于是引入抽象工厂。

4. 抽象工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Factory{
public Food getFood(){}
public Drink getDrink(){}

}
class KFCFactory implements Factory{
public Food getFood(){
return new Hamburger();
}
public Drink getDrink(){
return new Cola();
}
}
class SanQinFactory implements Factory{
...
}

无论有多少产品等级,工厂就一类。

冰箱电视洗衣机视为产品等级,工厂厂家海尔海信华为系列产品视为产品簇。虽然新增一个工厂很便捷,但抽象工厂扩展产品等级需要所有的工厂都修改,用Spring框架解决。

抽象工厂中可以生产多个产品,这多个产品之间必有内在联系。同一个工厂中的产品都属于一个产品簇

5. 原型模式

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
public class Sheep implements Cloneable{
private String name;
private int age;
private String color;
//构造器
public Sheep(String name,int age, String color){
this.name = name;
this.age = age;
this.color = color;
}
//提供对外的接口
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
...
//克隆该实例
protected Object clone(){
Sheep sheep = null;
try{
sheep = (Sheep)super.clone();//sheep是object,但是object不一定是sheep
}catch(Exception e){
System.out.println(e.getMessage());
}
return sheep;
}
}

Java中的Object类是所有类的根类,Object类提供了一个clone()的方法。需要实现clone的java类必须实现一个接口Cloneable,该接口表示该类能复制且有复制的能力。

上例的clone实现使用了默认的clone(),是浅拷贝,要实现深拷贝可以采用重写clone函数或者序列化

c++可以用拷贝构造函数

1
2
3
4
5
6
7
8
9
10
11
12
class ISplitter{
public:
virtual void split() = 0;
virtual ISplitter* clone() = 0;//纯虚函数
virtual ~ISplitter(){}
}
class BinarySplitter: public ISplitter{
public:
virtual ISplitter* clone(){
return new BinarySplitter(*this);
}
}

6. 建造者模式

建造产品的过程的产品解耦合?

与工厂模式的区别:

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
//Product
public class House{
private String baise;
private String wall;
private String roofed;
public String getBaise(){
return baise;
}
public void setBaise(){
this.baise = baise;
}
...
}
//抽象建造者
public abstract class HouseBuilder{
protected House house = new House();

public abstract void buildBasic();
public abstract void buildWall();
public abstract void roofed();

public House buildHouse(){
return house;
}
}

public class CommonHouse extends HouseBuilder{
public void buildBasic(){
System.out.println("普通房子打地基5m");
}
public void buildWall(){
System.out.println("普通房子打砌墙10cm");
}
public void roofed(){
System.out.println("普通房子打顶");
}
}

public class HighHouse extends HouseBuilder{
public void buildBasic(){
System.out.println("高楼打地基100m");
}
public void buildWall(){
System.out.println("高楼打砌墙20cm");
}
public void roofed(){
System.out.println("高楼打顶");
}
}

...//可扩展房子类型

//建造指挥
public class HouseDirector{
HouseBuilder houseBuilder = null;
//构造器传入houseBuilder
public HouseDirector(HouseBuilder houseBuilder){
this.houseBuilder = houseBuilder;
}
//setter传入houseBuilder
public void setHouseBuilder(HouseBuilder houseBuilder){
this.houseBuilder = houseBuilder;
}
public House constructHouse(){
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.buildHouse();
}
}
//用户
public class Client{
public static void main(){
CommonHouse commonHouse = new CommonHouse();
HouseDirector houseDirector = new HouseDirector(commonHouse);
House house = houseDirector.constructHouse();
}
}

未完待续…



本文标题:设计模式

文章作者:tsuki

发布时间:2020.11.08 - 11:42

最后更新:2020.11.08 - 12:07

原始链接:https://tsuki419.github.io/设计模式.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------THE END-------------
0%