0%

状态模式是针对系统的状态转换的,其主要的定义如下:

1
状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了它的类。

为了方便状态转移 我们为状态定义一个通用的接口,然后每一种状态都实现这个接口,而在系统类中,通过构造函数,将系统本身传入状态类中,这样,每一种状态的改变,都可以在自己类的内部完成,同时提高了可扩展性:

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
public interface State{
public void des();
public void action();
}
public class State1 implements State{
Sys sys;
public Sate1(Sys s)
{
this.sys=sys;
}
public void des(){
.../ implements
}
public void action(){
.../ change the state
sys.setState(s.getState2());
}
}
public class State2 implements State{
Sys sys;
public Sate2(Sys s)
{
this.sys=sys;
}
public void des(){
.../ implements
}
public void action(){
.../ change the state
sys.setState(s.getState1());
}
}
public class Sys {
private State1 state1;
private State2 state2;
private State state;//record the system's state
....//state1 & state2's setter & getter
public Sys(State state)
{
this.state=state;
}
public void setState(State state)
{
this.state=state;
}
public void aciton()
{
state.action();
}
}

虽然在实现上 状态模式和策略模式以及模板方法有些相似 但是几个设计模式完全不一样,策略模式是将可以互换的行为封装起来,然后使用委托的方法决定使用哪一个行为,模板方法则是由子类决定具体的如何实现算法中的某些步骤,而算法的流程是给定的,而状态模式则封装的是基于状态的行为,并将行为委托到当前状态,由当前状态来决定具体行为。

1.迭代器模式完成的功能是和迭代器一样的,封装了对对象的顺序遍历,因为子类的对象集合的存储方式可能并不一致。但是存储的对象是一致的。

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
public classItem{
.....//各种属性
}
public class Set1{
item[] items;
...
public Iterator createIterator(){
return new ItemIterator(items);
}
}
public class Set2{
ArrayList items;
...
public Iterator createIterator(){
return items.iterator();
}
}
public class ItemIterator implements Iterator{
Item[] items;
int position;
public ItemIterator(Item[] items)
{
this.items=items;
position=0;
}
public Object next()
{
Item i=items[position];
position=position+1;
return i;
}
public boolean hasNext()
{
if (position>=items.lenght || items[position]==null)
return false;
else
return true;
}
}

通过这种方法,我们就可以通过自己定义的一个迭代器来访问数组,同时通过createIterator的方法来顺序遍历存储结构不一样的Set1和Set2中item对象。所以迭代器模式就是:

1
迭代器模式:提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露其内部的表示。

2.组合模式

组合模式其实就是整体与部分的一个关系,其实就是一个树形结构,根节点由他的子节点组合而成,而子节点又有自己的子节点来组合而成,所以组合模式的定义如下:

阅读全文 »

前面学习过了策略模式,策略模式是对一类的算法进行封装,利用组合,算法之间可以互相替换,但是这个是针对算法过程不是一样的算法。但是如果一系列的算法的步骤都是一样的,且算法的很多过程都是一样的处理,那么,用策略模式的话,会导致算法的重用不高,我们采用模板方法来实现:

1
模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class CAL{
public final void algorithm()
{
A1();
A2();
if (Judge())
A3();
A4();
}
public void A1(){
//实现
.....
}
public void A2(){
//实现
.....
}
public abstract void A3(){}
public abstract void A4(){}
public boolean Judge(){
return true;
}
}

其中模板类是一个抽象类,其中算法是确定了的,A1,A2是公共的方法,所有的子类都是一样的,A3,A4是子类自己实现的不一样的函数,定义为抽象方法,子类实现,而Judge方法被成为钩子,默认返回true,而子类可以重写这个方法,这样就能让子类拥有自己的方法。但是这个也反应了模板方法的一个缺点,就是与策略模式相比,弹性不足。

阅读全文 »

1.适配器模式

适配器模式是针对接口不一时处理的情况,比如我的类的参数是IInterface1,但是我现在想要调用IInterface2接口的函数,怎么办呢?就是用适配器来解决这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface IInterface1(){
public void method1();
}
public interface IInterface2(){
public void method2();
}
public class adapter implements IInterface1{
IInterface2 v;
public adapter(IInterface2 t){
this.v=t;
}
public void method1(){
v.method2();
}
}

现在我们调用IIterface2的method1的方法的时候,就是可以直接构造一个适配器来完成

1
2
3
4
5
6
7
8
9
10
11
12
public class A{

public void method3(IInterface1 t)
{
t.method1();
}

public static void main(String[] arg)
{
(new A()).method3(new adapter(claimplementInterfce2));
}
}

其中claimplementInterface2是实现Interface2的一个类的实例。这种适配器的方法被称作为对象适配器,还有一种适配器,叫做类适配器,是基于类的多继承的,其中适配器继承自要适配的两个类,用其中一个类的方法调用另一个类,思想是一致的,不过java不支持多继承,所以也就是只能用对象适配器。

阅读全文 »

命令模式这个设计模式更像是对接口编程的一种应用,比如给小朋友穿衣服,但是不一样的衣服有不一样的穿法,裤子,衬衫,鞋,T恤都是不一样的,但是小朋友不知道怎么穿,只知道想穿什么,那么怎么办呢,小朋友会让他的妈妈帮他穿,这里面的“让妈妈帮忙”,就是给妈妈一个命令(虽然不是很恰当- -!),对小朋友而言,怎么穿他并不关心,反正只要有只要让妈妈穿就行了,所以我们只要定义一个穿的接口就行

1
2
3
4
public interface Wear()
{
public void excute();
}

然后继承这个穿,有很多种执行方式,比如穿鞋,穿衬衫,穿裤子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class WearShoe implements Wear{
public void excute()
{
.....//穿鞋的动作
}
}
public class WearShirt implements Wear{
public void excute()
{
.....//穿衬衫的动作
}
}
public class WearPants implements Wear{
public void excute()
{
.....//穿裤子的动作
}
}
阅读全文 »

工程中,某些对象我们只需要一个,比如线程池,缓存,对话框等的对象,我们通常的做法是可以定一个全局静态变量,然后通过程序初始化的时候就实例化他们,然后直接调用这个全局变量,但是这样有个问题,如果我的这个对象消耗的资源很多,而有的时候,我的程序在运行过程中又没用到这个对象,岂不是浪费了很多资源。通常的做法就是定义全局静态变量的时候,不初始化他,而是在调用过程中实例化,这样的话,对于全局变量的实例化,我们就要判断这个变量是否已经实例化了,如果实例化了的吧,我们就不对它进行实例化,所以代码如下:

阅读全文 »

在面向对象的编程中,我们常常会用到new这个关键字,同时,面向对象可以实现多态,这样的话,我们常常就会用父类或者接口定义一个变量,在用到这个变量的时候,再new一个具体的对象,但是有的时候,这个new的对象不是确定的,可能是要根据不同的场景,new出不同的子类,这个很简单的就可以通过if 或者switch来判断实现,但是,这样子以来的话,如果在很多个地方都出现了这种情况,岂不是都要在这些个地方来写这些一样的代码?这样真的好么?

工厂模式就是用来解决这种对象的生成的办法。工厂模式主要分为3种:简单工厂,工厂方法,抽象工厂。

阅读全文 »

​ 这一章看完之后,我感觉,装饰者模式就是对类继承的一种递归调用式的组合应用,很好的是实现了开闭原则,可以有效的扩展应用程序。比如书中的例子,有几种饮料,每种饮料的价格已经知道了,但是我们又有很多种的调料,每种调料也有它的价格,我们现在需要是在饮料中加调料,那么这样一来,饮料的售价就会变化,如何来描述这种售价呢?如果通过对调料种类的组合来定义若干的类,肯定是非常愚蠢的行为。

​ 通过装饰者模式,就能很好的解决这个问题,我们将这些类分为装饰类(调料),待装饰类(饮料)两种,这两种类继承同一个父类,不同的是装饰类中的构造函数有一个父类引用的构造函数,这样子就可以递归调用构造函数来进行 装饰了。

1
2
3
4
5
6
7
8
9
10
11
12
public class A extends BaseClass{

public string who()
{
return "A";
}

public int cost()
{
return 5;
}
}

我们定义一个待装饰类A,再定义几个装饰类:

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
public class decorator1 extends BaseClass{
BaseClass baseClass;
public decorator1(BaseClass t)
{
this.baseClass = t;
}
public string who()
{
return baseClass.who()+",decoratro1";
}
public int cost()
{
return baseClass.cost()+10;
}
}
public class decorator2 extends BaseClass{
BaseClass baseClass;
public decorator2(BaseClass t)
{
this.baseClass = t;
}
public string who()
{
return baseClass.who()+",decoratro2";
}
public int cost()
{
return baseClass.cost()+20;
}
}

然后我们在用decorator1 和decorator2 来装饰A的时候,就有了很犀利的调用方法:

1
2
3
4
5
A  a;
a=new decorator1(a);
a=new deocorator2(a);
system.out.println(a.who());
system.out.println(a.cost());

这样子 输出就是

1
2
A,decorator1,decorator2
35

实际的调用过程就是一个递归的过程。

装饰者模式的定义:

1
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更具有弹性的替代方案

其中用到的设计原则:

1
开闭原则:对扩展开放,对修改关闭

在项目设计阶段,处理一对多的依赖关系类的时候,我们需要降低代码的耦合性从而增强可扩展性,比如一个班级,班主任老师和学生的关系,对于学校的通知,必定不会是学生没事的时候就问一下班主任”学校有通知没啊?”(铁定会把班主任搞毛的),明智的做法则是等着班主任在班级里面通知(对于学校的通知,班主任不会不通知学生的),在这个关系里,班主任就是所谓的被观察者,而学生则是观察者,也就是所谓的观察者模式:

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态的时候,他的所有依赖都会收到通知并自动更新

阅读全文 »

​ 在实际开发过程中,经常会发生这样的一件事,我们需要实现一系列的功能,这些功能在逻辑上是可以抽象成一样的方法,不同的实现,也就是多态,有一种解决方法是,设计一个基类,然后我们定义一些方法,然后继承这个类,设计不同的子类,不同的实现,这样子我们就可以定义基类来调用子类的方法,实现多态,这种方法一定程度上是实现了代码复用。

​ 但是会有一个问题,假设,基类BaseClass具有一个方法,他们的子类都具有两个方法A和B,其中方法A的实现,所有的子类都一样,很明显A的实现方法是放在基类中实现的,如果B的方法每个子类的实现都不是一样的,那么毫无疑问的是我们会在每个子类中重写B的实现。这些都是显而易见的,但是某一天需求变了,BaseClass的子类childClass1,childClass2的B方法的实现是完全一样的,childClass3,childClass4的B方法的实现也是一样的,如果我们再在每个子类中实现这个方法,很明显,代码复用很不完美。也许我们会这样子解决这个问题:

阅读全文 »
×