观察者模式
多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新
观察者模式主要角色有:抽象主题角色:也叫抽象目标类,提供了一个用于保存观察者对象的聚集类和增加,删除观察者对象的方法,以及通知所有观察者抽象方法
具体主题角色:也叫具体目标类,实现抽象目标中的通知方法,当具体主体的内部状态发生改变,通知所有注册过的对象
抽象观察者角色:是一个抽象类接口,包含一个更新自己的抽象方法,接到具体主题的更改通知时调用
具体观察者角色:实现抽象观察者中定义抽象方法,以便在得到目标的更改通知时更新自身状态
观察者模式首先有一个观察类,这个类中有一个ArrayList存放观察者们,除此之外还有类状态和设置,获取状态的方法,状态改变时通知所有观察者,观察者类可以有个抽象类,所有观察者类继承这个抽象类,观察者类有要观察的对象
优点:降低目标与观察者的耦合关系,两者间时抽象耦合关系,目标与观察者间建立了一套触发机制
缺点:目标与观察者间依赖关系没有完全解除,并且可能出现循环引用,当观察者对象多时,通知的发布会花费很多时间
//抽象观察者角色
public interface A{
public void getMsg(String msg);
}
//观察者角色
public class B implements A{
private String name;
public B(String name){
this.name = name;
}
public void getMsg(String msg){
sout(name+"接收消息"+msg);
}
}
//抽象主题
public interface P{
public void add(B b);
public void remove(B b);
public void setMsg(String msg);
public void sendMsg();
}
//具体主题
public class AP implements P{
List<A> list = new ArrayList<A>();
//设置消息
private String msg;
public void add(A a){
list.add(a);
}
public void remove(A a){
list.remove(a);
}
public void setMsg(String msg){
this.msg = msg;
}
public void sendMsg(){
for(A a:list){
a.getMsg(msg);
}
}
}
模板方法
模板模式中一个抽象类公开定义执行它的方法方式,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行,这种类型的设计模式属于行为型模式
定义一个操作中的算法骨架,将步骤延迟到子类执行,模板方法使子类可以不改变算法的结构重定义该算法的某些特定功能
优点:封装不变部分,扩展可变部分 || 提取公共代码,便于维护 || 行为由父类控制,子类实现
缺点:每个不同实现都要一个子类实现,导致该类个数增加,使系统更加庞大
使用场景:多个子类共有的方法,逻辑也应相同
重要的复杂的方法,可以考虑作为模板方法
注意事项:为防止恶意操作,一般模板方法都加上final关键词
//定义操作接口
public abstract class C{
//不能被子类重写--final
public final void cc(){
a();
b();
d();
e();
}
void a(){};
void b(){};
void d(){};
void e(){};
}
//执行操作
public class F extends C{
void a(){
sout("执行操作a");
}
void b(){
sout("执行操作b");
}
void d(){
sout("执行操作d");
}
void e(){
sout("执行操作e");
}
}
//测试类
public class CTest{
public static void main(String[] args){
F f =new F();
f.cc();
}
}
策略模式
将类中经常改变或可能改变的部分提取为一个抽象策略接口类,然后在类中包含这个对象的实例,这样实例在运行时就可以随意调用该接口的类行为
优点:算法可以自由切换(策略类自由切换) || 避免使用多重条件判断 || 扩展性良好(符合开闭原则)
缺点:策略类会增多 || 所有策略类都需对外暴露 || 客户端必须知道所有策略类才能确定要调用的策略类
public class C{
private CuX cuX;
public CuXC(CuX cuX){
this.cuX = cuX;
}
//定义算法方法
public void use(){
cuX.cux();
}
}
public interface CuX{
void cux();
}
public class Sfa implements CuX{
public void cux(){
sout("使用算法a");
}
}
public class Sfb implements CuX{
public void cux(){
sout("使用算法b");
}
}
public class CuXTest{
public static void main(String[] args){
Sfa sfa = new Sfa();
C c = new C(sfa);
c.use();
}
}