default

设计模式

Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

Adpater:将一个类的接口转换成客户希望的另外一个接口。 由于接口不兼容而不能一起工作的那些类可以一起工作。

Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

Compsite:将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e使得客户对单个对象和复合对象的使用具有一致性。

Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言,D e c o r a t o r模式比生成子类方式更为灵活。

Facade:为子系统中的一组接口提供一个一致的界面,F a c a d e模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。

FlyWeight:运用共享技术有效地支持大量细粒度的对象。

Interpreter:给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 器使用该表示来解释语言中的句子。

Iterator:提供一种方法顺序访问一个聚合对象中各个元素 内部表示。

Meditor:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

Memento:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。

Observe:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。

Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型创建新的对象。

Proxy:为其他对象提供一个代理以控制对这个对象的访问。

Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。

Strategy:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模

式使得算法的变化可独立于使用它的客户。

Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

设计模式简述

设计模式在粒度和抽象层次上各不相同,由于众多的设计模式,我们可以将他们组织起来。将设计模式进行分类可以方便我们进行引用。
designmodezone

我们根据两条准则进行分类:

  • 创建型设计模式与对象的创建有关
  • 结构型模式与类和对象的组合有关
  • 行为型设计模式对类和对象怎样交互和怎样分配职责进行描述。

单例模式

举个例子:
有一个仓库
想要使用代码完成仓库的管理,简历仓库类和工人类

出现的问题:
通过测试发现,每次工人搬运操作都会新建一个仓库,就是货物都不是放在同一仓库,这是怎么回事呢?(看下面代码)

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

//仓库类
class StoreHouse {
private int quantity = 100;

public void setQuantity(int quantity) {
this.quantity = quantity;
}

public int getQuantity() {
return quantity;
}
}

//搬货工人类
class Carrier{
public StoreHouse mStoreHouse;
public Carrier(StoreHouse storeHouse){
mStoreHouse = storeHouse;
}
//搬货进仓库
public void MoveIn(int i){
mStoreHouse.setQuantity(mStoreHouse.getQuantity()+i);
}
//搬货出仓库
public void MoveOut(int i){
mStoreHouse.setQuantity(mStoreHouse.getQuantity()-i);
}
}

//工人搬运测试
public class SinglePattern {
public static void main(String[] args){
StoreHouse mStoreHouse1 = new StoreHouse();
StoreHouse mStoreHouse2 = new StoreHouse();
Carrier Carrier1 = new Carrier(mStoreHouse1);
Carrier Carrier2 = new Carrier(mStoreHouse2);

System.out.println("两个是不是同一个?");

if(mStoreHouse1.equals(mStoreHouse2)){//这里用equals而不是用 == 符号,因为 == 符号只是比较两个对象的地址
System.out.println("是同一个");
}else {
System.out.println("不是同一个");
}
//搬运工搬完货物之后出来汇报仓库商品数量
Carrier1.MoveIn(30);
System.out.println("仓库商品余量:"+Carrier1.mStoreHouse.getQuantity());
Carrier2.MoveOut(50);
System.out.println("仓库商品余量:"+Carrier2.mStoreHouse.getQuantity());
}
}

实现一个类,只有一个实例化对象&只提供一个全局访问点

解决问题的方式:

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
//单例仓库类
class StoreHouse {

//仓库商品数量
private int quantity = 100;
//自己在内部实例化
private static StoreHouse ourInstance = new StoreHouse();;
//让外部通过调用getInstance()方法来返回唯一的实例。
public static StoreHouse getInstance() {
return ourInstance;
}

//封闭构造函数
private StoreHouse() {
}

public void setQuantity(int quantity) {
this.quantity = quantity;
}

public int getQuantity() {
return quantity;
}
}


//搬货工人类
class Carrier{
public StoreHouse mStoreHouse;
public Carrier(StoreHouse storeHouse){
mStoreHouse = storeHouse;
}
//搬货进仓库
public void MoveIn(int i){
mStoreHouse.setQuantity(mStoreHouse.getQuantity()+i);
}
//搬货出仓库
public void MoveOut(int i){
mStoreHouse.setQuantity(mStoreHouse.getQuantity()-i);
}
}

//工人搬运测试
public class SinglePattern {
public static void main(String[] args){
StoreHouse mStoreHouse1 = StoreHouse.getInstance();
StoreHouse mStoreHouse2 = StoreHouse.getInstance();
Carrier Carrier1 = new Carrier(mStoreHouse1);
Carrier Carrier2 = new Carrier(mStoreHouse2);

System.out.println("两个是不是同一个?");

if(mStoreHouse1.equals(mStoreHouse2)){
System.out.println("是同一个");
}else {
System.out.println("不是同一个");
}
//搬运工搬完货物之后出来汇报仓库商品数量
Carrier1.MoveIn(30);
System.out.println("仓库商品余量:"+Carrier1.mStoreHouse.getQuantity());
Carrier2.MoveOut(50);
System.out.println("仓库商品余量:"+Carrier2.mStoreHouse.getQuantity());
}
}

写两种多线程加高性能写法

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
class SingleTon{
private static volatile SingleTon instance;
private SingleTon(){}
public SingleTon getInstance(){
//first if, reduce the spend for accquire lock
if(instance == null){
synchronized(SingleTon.class){
if(instance == null){
instance = new SingleTon();
}
}
return instance;
}
}
}
//静态内部类
class SingleTon2{
private SingleTon2(){}
private static class SingleTonHolder{
private static final SingleTon INSTANCE = new SingleTon();
}
public static SingleTon getInstance(){
return SingleTon.INSTANCE;
}
}

策略模式

举个例子:
我有一个百货公司,最近准备促销活动,冲突
每个节日使用一个促销活动太枯燥,没有吸引力

第一步: 定义一个抽象策略角色:百货公司所有促销活动共同使用

1
2
3
public abstract class Strategy{
public abstract void show();
}

第二部:定义具体策略角色,每个节日具体的促销活动

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
//为春节准备的促销活动A
class StrategyA extends Strategy{

@Override
public void show() {
System.out.println("为春节准备的促销活动A");
}
}

//为中秋节准备的促销活动B
class StrategyB extends Strategy{

@Override
public void show() {
System.out.println("为中秋节准备的促销活动B");
}
}

//为圣诞节准备的促销活动C
class StrategyC extends Strategy{

@Override
public void show() {
System.out.println("为圣诞节准备的促销活动C");
}
}

定义一个context,进行上下文感知

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
class Context_SalesMan{
//持有抽象策略角色的引用
private Strategy strategy;

//生成销售员实例时告诉销售员什么节日(构造方法)
//使得让销售员根据传入的参数(节日)选择促销活动(这里使用一个简单的工厂模式)
public SalesMan(String festival) {
switch ( festival) {
//春节就使用春节促销活动
case "A":
strategy = new StrategyA();
break;
//中秋节就使用中秋节促销活动
case "B":
strategy = new StrategyB();
break;
//圣诞节就使用圣诞节促销活动
case "C":
strategy = new StrategyC();
break;
}

}

//向客户展示促销活动
public void SalesManShow(){
strategy.show();
}

}

当我们具体使用的时候我们可以通过上下文去进行具体的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class StrategyPattern{
public static void main(String[] args){

Context_SalesMan mSalesMan ;

//春节来了,使用春节促销活动
System.out.println("对于春节:");
mSalesMan = Context_SalesMan SalesMan("A");
mSalesMan.SalesManShow();


//中秋节来了,使用中秋节促销活动
System.out.println("对于中秋节:");
mSalesMan = Context_SalesMan SalesMan("B");
mSalesMan.SalesManShow();

//圣诞节来了,使用圣诞节促销活动
System.out.println("对于圣诞节:");
mSalesMan = Context_SalesMan SalesMan("C");
mSalesMan.SalesManShow();
}
}

优点: 我们只通过一个接口,就可以使得他们之间进行灵活的调用

增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“

适配器模式

场景
有一个电源插座,现在国内的事220v的,希望有一个转接头能转换成110v的

首先我们先实现一个接口,代表我们期望使用的

1
2
3
public interface Target {
public void Convert_110v();
}

其次我们需要实现一个原有的插头

1
2
3
4
5
//adapatee
class PowerPort220V{
public void output220v();
}

接下来我们需要创建一个adapter

1
2
3
4
5
6
7
8
9
10
11
class Adapter220V extends PowerPort220V implements Target{
//期待的插头要求调用Convert_110v(),但原有插头没有
//因此适配器补充上这个方法名
//但实际上Convert_110v()只是调用原有插头的Output_220v()方法的内容
//所以适配器只是将Output_220v()作了一层封装,封装成Target可以调用的Convert_110v()而已

@Override
public void Convert_110v(){
this.Output_220v;
}
}

此时我们可以直接去通过一个中间类(adapter去进行转换而不需要再去调用原有的220v的输出

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
//进口机器类
class ImportedMachine {

@Override
public void Work() {
System.out.println("进口机器正常运行");
}
}


//通过Adapter类从而调用所需要的方法
public class AdapterPattern {
public static void main(String[] args){

Target mAdapter220V = new Adapter220V();
ImportedMachine mImportedMachine = new ImportedMachine();

//用户拿着进口机器插上适配器(调用Convert_110v()方法)
//再将适配器插上原有插头(Convert_110v()方法内部调用Output_220v()方法输出220V)
//适配器只是个外壳,对外提供110V,但本质还是220V进行供电
mAdapter220V.Convert_110v();
mImportedMachine.Work();
}
}

代理模式

背景: 我希望买个电脑,但是国内没有,我需要代购
首先我定义一个需要proxy做的事情

1
2
3
4
public interface Subject{
//这里定义我希望别人做的
public void buyMac();
}

创建一个真实的对象

1
2
3
4
5
6
public class RealSubject implements Subject{
@Override
public void buyMac(){
System.out.println("I buy");
}
}

创建一个代理类,通过代理去进行实现,同时创建其对象,访问其中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Proxy  implements Subject{

@Override
public void buyMac{

//引用并创建真实对象实例,即”我“
RealSubject realSubject = new RealSubject();

//调用真实对象的方法,进行代理购买Mac
realSubject.buyMac();
//代理对象额外做的操作
this.WrapMac();
}

public void WrapMac(){
System.out.println(”用盒子包装好Mac“);
}
}

优势:
代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
协调调用者和被调用者,降低了系统的耦合度