学习到现在的主要问题是没有进行例子的完美历练,说白了,就是没动手亲自的试试,写写对应的代码,理解一下主要的设计思想,这个应该是学习设计模式我最重要的地方,那么现在针对之前学习的设计模式做一个总结和回顾吧
0.设计模式分析规律
在讲解这个设计模式之前,我们应该学习到设计的原则,1.分析程序中变化的位置,针对变化的位置进行封装隔离
分析是对鸭子的叫声和会飞进行了特殊的隔离,因为这两种行为是特殊于其他普通鸭子的行为,这里考虑的就是封装这个变化
第一种角度:我们考虑之前的行为都是采用继承的关系,但是这样所有的子类都具有叫声和飞行的行为了,不能这样用
第二种角度:我们采用接口的形式,让父类实现这两个接口,其他子类进行覆盖,有的鸭子就覆盖,没有就不覆盖,这样的写法带来的问题是,以后要是有新的行为加入进来,子类和父类还要修改
引入第二个设计原则:针对接口编程,而不是实现编程
那么这样考虑以后,有了另一种角度
第三种角度:设计两个接口,一个叫,一个飞行,然后写各自的实现类,叫声类,和飞行类,将这两个类的接口行为组合在鸭子的父类中,即鸭子父类持有这两个行为接口,
父类写两个方法,使得有些鸭子可以请求叫方法,有的可以请求飞行的方法,让子类来传递飞行和叫的方式,比如:有的“呱呱叫” 有的不叫,有的飞行有的像火箭一样
为了实时修改这两个类,加入设置的set方法动态修改叫和飞行的行为
问题:这里父类也有了叫和飞行的行为,是不是违背了之前说的不用继承,特殊行为应该在某些子类上
问题:这里要考虑我们之前说的变化是什么?1,叫和飞行的行为区别于一般鸭子,只是这样的一种,2.叫和飞行的行为有一类这样的行为了
1.策略设计模式
上面的例子貌似是特意为策略设计模式制定的,那么我们该怎么样分析这个模式
算法簇的替换,而不影响其他的行为
模式结构:一个接口,多个实现类,用这个接口来维护一种或多种行为,不同的实现类相互替换(非典型的策略模式)
//飞行接口
public interface FlyBehavor{
void fly();
}
//飞行行为类
public RebotFly implements FlyBehavor{
public void fly(){
//添加自身的非行为
}
}
public class Duck{
private FlyBehavor mFlyBehavor;
public Duck(FlyBehavor mFlyBehavor){
this.mFlyBehavor = mFlyBehavor;
}
public void performFly(){
mFlyBehavor.fly();
}
}
思考:
1.典型的策略模式的结构和适用场景
策略模式典型是Context(场景),Strategy(接口策略),策略子类,场景对接口策略进行持有,利用子类替换达到不同算法的目的
适用场景:用同一个方法,来计算不同的业务关系,制定不同算法
2.适用构造方法传参,还是适用setter方式,有什么区别,各有什么优缺点?
构造方法在初始化定义传入参数,setter方式是改变当前对象的持有属性,setter用于一个对象多次改变自身属性
2.状态模式
状态模式是对象通过改变自身的属性,来改变其行为(方法),达到消除条件判断语句的作用
状态模式的结构重点:
ContextState(对象场景),State(对象持有状态属性),状态子类,状态子类和策略子类的区别就是状态子类通过方法传递入参ContextState来修改本身状态
1 public class ContextState{
2 public State mState;
3 public int hour;//状态属性
4 public void setState(State state){
5 mState = state;
6 }
7 public void request(){
8 mState.handle(this)
9 }
10 }
11
12 public interface State{
13 void handle(ContextState state);
14 }
15
16 public StateA implement State{
17 public void handle(ContextState context){
18 //这里用来改变当前对象的状态
19 context.state = new StateB();
20 if(context.hour < 12){
21 //上午工作很充实
22 }else{
23 //不符合条件继续向下分发
24 context.setState(new StateB());
25 context.request();
26 }
27 }
28 }
29 public StateB implement State{
30 public void handle(ContextState context){
31 //这里用来改变当前对象的状态
32 context.state = new StateA();
33 if(context.hour < 12){
34 //上午工作很充实
35 }else{
36 //不符合条件继续向下分发
37 context.setState(new StateA());
38 context.request();
39 }
40 }
41 }
以上代码仅供参考
思考:
1.状态模式必须有相应的状态属性吗?这种状态可以用枚举来代替吗?
2.状态模式适用的场景有哪些,是通过什么样的出发点来使用状态模式的?
状态模式的出发点就是对象本身状态的改变来修改行为,那这种状态可以是多个吗?
3.观察者模式
相关例子的引入是做一个气象发布器,将系统发布的气象信息显示在多个公告栏上
多个公告栏的实时更新是核心部分,变化的位置是在哪里?比如添加或减少一个信息公告栏,信息公告栏的主要功能变化,公告栏的外观的变化,发布信息的数据结构变化(接入其他系统的气象信息)
之前的设计方式是否合理,这个是根据OO设计经验来完成的,要多积累才行
之前的设计是在气象更新器中写死气象信息更新的类,有信息更新,就发送给公告栏,这样的设计有什么问题吗?
问题1.如果多个公告栏中有一个不用了,这样我们要手动删除代码,测试,
问题2.气象加入了新的公告信息,加入新的字段,比如温度,湿度,风向,级别
问题3.OO设计思想是什么?为什么要这样用?
问题1.违反了OO设计原则:对扩展开发,对修改关闭
问题2.将所有的类统一成一个整体
问题3.设计类交互的松耦合而努力
模式结构:
"推"消息
被观察者(气象站) 观察者(公共栏)
拥有对所有观察者的引用(集合) 提供一完整的更新接口(update)
信息更新(遍历,将气象信息传递给公共栏)
-----------------------------------------------------------------------------------
"拉"消息
被观察者(气象站) 观察者(公共栏)
拥有对所有观察者的引用(集合) 提供一完整的更新接口(update(obseverable,obj)
信息更新(遍历,将气象信息传递给公共栏)
观察者模式主要的结构
一个被观察者,多个观察对象,当被观察者改变时通知其他观察对象作出改变(一个对象内部状态改变的同时通知其他对象改变)
被观察者拥有观察者的集合,并且拥有添加和移除,通知方法,观察者有抽象的更新数据接口
思考:
1.怎样实现一个对象既是观察者也是被观察者,在Java中有系统库可以实现吗?
2.观察者模式适用的场景有哪些?
4.装饰模式
作用:对一个对象已有功能动态的添加更多功能的一种方式
优点:有效的区分类的核心功能和装饰功能,在特殊时间或特定时期给核心功能添加部分装饰
代码结构:
一个通用的装饰接口,装饰类及其子类,
//接口
public interface Compent{
void Operation();
}
//装饰类
public Decorate implement Compent{
protected Compent mCompent;
public void setCompent(Compent compent){
mCompent = compent;
}
public void Operation(){
mCompent.Operation();
}
}
//装饰类的子类
public DecorateA extends Decorate{
private String msg;
public void Operation(){
//添加文案输出功能
System.out.println(msg);
super.Operation();
}
}
//特殊情况下,装饰类和装饰子类可以进行合并