设计模式-读书笔记2
结构型模式
适配器模式 不兼容结构的协调 220v接入20v的笔记本电脑 别名包装器 Wrapper
适配器类Adapter 适配者类Adaptee 目标抽象类 Target
//demo1
class Adapter extends Target{
private Adaptee adaptee; //维持对一个适配者对象的引用
public Adapter (Adaptee adaptee){
this.adaptee = adaptee;
}
public void request(){ // 转发调用
adaptee.specificRequest();
}
}
当target 和adaptee双向调用时,双向适配器模式
//demo2
class Adapter implements Target,Adaptee{
private Adaptee adaptee; //同时维持对适配者和目标类的引用
private Target target;
public Adapter (Adaptee adaptee){
this.adaptee = adaptee;
}
public void request(){ // 转发调用
adaptee.specificRequest();
}
}
缺省适配器模式:当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求,它适用于不想使用一个接口中的所有方法的情况,又称单接口适配器模式
桥接模式 处理多维度变化 颜色、系统 分类抽象接口和实现
//demo1
//实现类接口
interface ImageImp{
public void doPaint(Matrix m); //显示像素矩阵m
}
//具体实现类
class WindowImp implements ImageImp{
public void doPaint(Matrix m){
sout("在windows系统上显示")
}
}
//抽象类
abstract class Image{
protected ImageImp imp; //定义实现类接口对象
public void setImageImp(ImageImp imp){
this.imp = imp;
}
public abstract void parseFile(String fileName); //声明抽象业务方法
}
//扩充抽象类
class JPGImage extends Image{
public void parseFile(String fileName){
Matrix m = new Matrix;
imp.doPaint(m); //调用实现类的方法
sout("格式为jpg")
}
}
组合模式 树形结构的处理 处理文件夹及下面的文件
定义一个抽象构建类,既可以代表叶子,又可以代表容器
//demo1
//抽象构件
abstract class Component{
public abstract void add(Component a); //新增
public abstract void del(Component a); //删除
public abstract void operation(); //业务方法
}
//叶子构件
class Leaf extends Component{
add。。。。
。。。。
}
//容器构件
class Composite extends Component{
private ArrayList<Component> list = new ArrayList<Component>();
add{list.add(c)}。。。。
。。。。
public void operation(){
//容器构件具体业务方法的实现
//递归调用成员构件的业务的方法
for(Object obj:list){
((Component)obj).operation();
}
}
}
P162 12.5 22:08留
透明组合模式:抽象构件类Compenent 有所有方法,提供默认实现
安全组合模式:抽象构件类Compenent 没有管理成员对象的方法,如叶子节点leaf不需要的add等方法
装饰模式 扩展系统功能 对象结构型
动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更加灵活
抽象构件Compoent:是具体构件和抽象装饰类地共同父类
具体构件ConcreteComponent:
抽象装饰类:Decorator 给具体构件增加职责,但具体职责在其子类中实现
具体装饰类:ConcreteDecorator
//demo1抽象装饰类的设计
class Decorator implements Component{
private Component component; // 维持一个对抽象构件对象的引用,注入一个抽象构件类型的对象
public Decorator(Component component){
this.component = component;
}
public void operation(){
component.operation(); //调用原有业务方法
}
}
//具体装饰类中
class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component){
super(component);
}
public void operation(){
super.operation(); //调用原有业务方法
addedBehavior(); //调用新增业务方法
}
public void addedBehavior(){
.....
}
}
//使用
Component component, componentSB; //使用抽象构件定义
component = new Window(); // 定义具体构件
componentSB = new ConcreteDecorator(); //定义装饰后的构件
componentSB.display();
//也可以
Component componentBB; //全部使用抽象构件定义
componentBB = new ConcreteDecorator2(componentSB); //将装饰了一次之后的对象继续注入到另一个装饰类中进行第2次装饰
透明装饰模式
上面使用抽象构件类型定义对象,而不是具体构件类型,如
ConcreteDecorator2 componentBB = new ConcreteDecorator2(componentSB);
但是这无法调用具体装饰类中的新增行为
半透明装饰模式
Component component; //使用抽象类型定义
component = new Window();
ConcreteDecorator componentSB = new ConcreteDecorator(); //使用具体装饰类型定义
这不能实现对一个对象的多次装饰(传入调用)
外观模式 提供统一入口 facade
外观角色
//demo1
class Facade{
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
public void method(){
obj1.method();
obj2.method();
}
}
设计为单例类,定义了一个静态的Facade类型的成员变量instance,其构造函数为私有private
如果要一个子系统变为另一个,原有不再使用,这需要引入一个抽象外观类,客户端针对抽象外观类编程,而在运行时再确定具体外观类
//demo1
abstarct class AbstractFacade{
public abstract void method();
}
Class newFacade extends AbstractFacade{
}
享元模式 实现对象的复用,通过共享技术有效支持大量细粒度对象的复用
FlyWeight 抽象享元类
ConcreteFlyWeight 具体享元类
UnsharedConcreteFlyWeight 非共享具体享元类
FlyweightFactory 享元工厂类,通常只有一个
//demo1
class FlyweightFactory {
//定义一个HashMap用于存储享元对象,实现享元池
private HashMap flyweights = new HashMap();
public FlyWeight getflyweight(String key){
//如果对象存在,则直接从享元池获取
if(flyweights.containskey(key)){
return (Flyweight)flyweights.get(key);
}else{
//如果对象不存在,先创建一个新的对象添加到享元池中,然后返回
FlyWeight fw = new ConcreteFlyWeight();
flyweights.put(key, fw);
return fw;
}
}
}
内部状态:“a"始终是"a”
外部状态:"a"有的是红色的
//demo2
class FlyWeight{
//内部状态inState作为成员变量,同一个享元对象其内部状态是一致的
private String instate;
public FlyWeight (String instate){
this.instate = instate;
}
}
//demo3
//外部状态exstate 在使用时由外部设置,不保存在享元对象中,即使是同一个对象,在每一次调用时可以传入不同的外部状态
public void operation(String exstate){
}
单纯享元模式:所有具体享元类都是可共享的
符合享元模式:其中包含的每个单元享元类外部状态相同,其内部状态不同,符合享元对象本身不共享
//demo4
String s1 = "ab";
String s2 = "a"+"b";
s1 == s2 true
代理模式 对象的间接访问
Proxy类
//demo1
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
返回一个动态创建的代理类的实例
第一个参数是代理类的类加载器
第2个参数是代理类所实现的接口列表(与真实主题类接口列表一致)
第3个参数是代理类所指派的调用处理程序类
//demo2
interface AbstractDao //抽象主题角色
class UserDaoo implements AbstractDao {} //真实角色 有个findUserById方法
//自定义请求处理程序类
class DaoLogHandler implements InvocationHandler{
private Object object;
public DaoLogHandler(){};
public DaoLogHandler(Object object){
this.object = object;
}
}
实现invoke方法,调用在真实主题类中定义的方法
//demo3
public Object invoke(Object proxy, Method method, Object[] args) throw Throwable{
//proxy是代理类的实例
//method需要代理的方法
//args代理方法的参数数组
Object result = method.invoke(object, args); // object转发调用
return null;
}
实现
//demo4
AbstraceDao dao = new UserDao();
InvocationHandler handler = new InvocationHandler(dao);
AbstraceDao proxy = null;
//动态创建代理对象,用来代理一个AbstractUserDao类型的真实主题对象
proxy = (AbstractDao)Proxy.newInstance(AbstraceDao.class.getClassLoader(), new Class[]{AbstractDao.class}, handler);
proxy.findUserById(); // 调用代理对象的业务方法
远程代理:访问远程主机
虚拟代理:如上,例如一个对象需要很久时间才能完成加载,用一个资源少的对象来代理一个消耗资源多的对象
保护代理:访问权限
缓冲代理:提供临时存储空间,以供多个客户端共享结果
智能引用代理:提供额外操作
与装饰不同,它目的在动态增加功能,且新职责在同一个问题域,而代理是不同问题域,目的在控制对象的访问
行为型模式
职责链模式 请求的链式处理
请求处理对象仅需维持一个指向后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的互相连接
//demo1
abstract class Handler{
//维持对下家的引用
protected Handler succesor;
public void setSuccesor(Handler succesor){
this.succesor = succesor;
}
public abstract void handleRequest(String request){
if(请求满足条件){
//处理请求
}else{
this.succesor.handlerRequest(request); //转发请求
}
}
}
命令模式 请求发送者与接收者解耦
//demo1
//抽象命令类
abstract class Command{
public abstract void execute();
}
//调用者
class Invoker{
private Command command;
//构造注入
public Invoker(Command command){this.command = command}
//设值setter注入
public void setCommand(Command command){this.command = command}
//业务方法 用于调用命令类的execute方法
public void call(){
command.execute();
}
}
//具体命令类
class ConcreteCommand extends Command{
private Receiver receiver; //维持一个对请求接收者对象的引用;
public void execute(){
receiver.action(); //调用请求接收者的处理方法
}
}
class Receiver{public void action(); //具体操作}
将请求发送者和接收者完全解耦
命令队列:将多个请求排队,增加一个CommandQueue类
//demo2
class CommandQueue{
//定义一个ArrayList来存储命令队列
private ArrayList<Command> commands = new ArrayList<Command>();
public void addCommand ~
//循环调用每一个命令对象的execute()方法
public void execute(){
for(Object command:commands){
((Command)command).execute();
}
}
}
//请求发送者Invoker中
private CommandQueue cq;
//调用方法
public void call(){
cq.execute();
}
解释器模式
自定义语言的实现
//demo1
//抽象表达式
abstract class AbstractExpression{
public abstarct void interpret(Context ex);
}
//终结符表达式
class TerminalExpression extends AbstractExpression{
public void interpret(Context ctx){}
}
//非终结符表达式
class NonTerminalExpression extends AbstractExpression{ //一个类对应一个规则
private AbstractExpression left;
private AbstractExpression right;
//构造注入.....
public void interpret(Context ctx){
//递归调用每一个组成部分的interpret方法,在递归调用时指定组成部分的连接方式,即非终结符的功能
}
}
迭代器模式 遍历聚合对象中的元素 存储数据和遍历数据分离
提供一种方式来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标cursor
//demo1
//抽象迭代器
interface Iterator{
public void first();
}
//具体迭代器
class ConcreteIterator implements Iterator{
private ConcreteAGG objects; //维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据
private int cursor; // 定义一个游标,用于记录当前访问位置
public ConcreteIterator(ConcreteAGG objects){
this.objects = objects;
}
public void first(){
......
}
}
//抽象聚合类
interface AGG{
Iterator createIterator();
}
//具体聚合类
class ConcreteAGG implements AGG{
public Iterator createIterator(){
return new ConcreteIterator(this);
}
}
//或在具体聚合类中使用内部类实现迭代器
private class Itr implements Iterator<E>{
int cursor=0;
。。。。。
}
如JDK内置的迭代器一样,Collection接口中有add方法 Iterator iterator()
以上不支持逆向遍历 ListIterator接口可支持
ListIterator i = c.listIterator();
P298 记录昨天下午看的内容 20:30留
中介者模式 协调多个对象之间的交互 网状变为星型
抽象中介者
//demo1
abstract class Mediator{
protected ArrayList<Colleague> colleagues; // 用于存储同事对象
//注册方法,用于增加同事对象
public void register(Colleague colleague){
colleagues.add(colleague);
}
//声明抽象的业务方法
public abstract void operation();
}
//具体中介者
class ConcreteMediator extends Mediator{
//实现业务方法,封装同事之间的调用
public void operation(){
.....
((Colleague)colleagues.get(0)).method(); //通过中介者调用同事类的方法
}
}
//抽象同事类
abstract class Colleague{
protected Mediator mediator; //维持一个抽象中介者的引用
//构造注入
public Colleague(Mediator mediator){
this.mediator = mediator;
}
public abstract void method(); //声明自身方法,处理自己的行为
public void method2(){
mediator.operation(); // 定义依赖方法,与中介者进行通信
}
}
//具体同事类
class ConcreteColleague extends Colleague{
public ConcreteColleague(Mediator mediator){
super(mediator);
}
//实现自身方法
public void method1(){.....}
}
增加新的同事类:
法1:直接在具体中介者中改
法2:增加具体中介者的子类,进行方法覆盖
备忘录模式 撤销功能的实现 别名Token
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就能在以后将对象恢复到原先保存的状态
//demo1
//原发器
public class Originator{
private String state;
public Originator(){}; // 创建备忘录对象
public Memento createMemento(){
return new Memento(this);
}
//根据备忘录对象恢复原发器状态
public void restoreMemento(Memento m){
state = m.state;
}
setState......getState.....
}
//为了保证备忘录的封装性,要与原发器一个包
class Originator{
private String state;
public Memento(Originator o){ //只由原发器控制,而不是负责人
state = o.getState();
}
setState。。。。getState....
}
//负责人
public class Caretaker{
private Memento memento;
public Memento getMemento(){
return memento;
}
public void setMemento(Memento memento)......
}
如果要多次撤销,负责人中定义ArraysList集合来存储多个备忘录
private ArrayList mementoList = new ArrayList();
观察者模式 对象间的联动
一对多 每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新
别名:发布-订阅 模型-视图 源-监听器 从属者
//demo1
//目标
abstract class Subject{
//定义一个观察者集合用于存储所有观察者对象
protected ArrayList observers<Observer> = new ArrayList();
//注册方法,用于向观察者集合中增加一个观察者
public void attach(Observer observer){
observers.add(observer);
}
//注销方法 删除 detach remove
//声明抽象通知方法
public abstract void notify();
}
//具体目标类
class ConcreteSubject extends Subject{
//实现通知方法
public void notify{
//遍历观察者集合,调用每一个观察者的响应方法
for(Object obs:observers){
((Observer)obs).update();
}
}
}
//抽象观察者
interface Observer{
//声明相应方法
public void update()
}
//具体观察者
class ConcreteObserver implements Observer{
实现.......
}
java.util.Observable 接口只有一个方法,充当抽象观察者 void update(Observable o, Object args)
java.util.Observable类,包含新增删除
发布者:事件源
订阅者:事件监听器
通过事件对象传递
P340 21:48 留
对象状态及其转换 状态模式
允许一个对象在其内部状态时,改变它的行为,对象看起来似乎修改了它的类
//demo1
//抽象状态类
abstract class State{
//声明抽象业务方法,不同的具体状态类可以用不同的方法实现
public abstarct void handle();
}
//具体状态类
class ConcreteState extends State{
public void handle(){
//具体方法实现代码
}
}
//环境类,实际上是真正拥有状态的对象
class Context{
private State state; // 维持一个对抽象状态对象的引用
private int value; //其他属性值,该属性值的变化可能会导致对象状态发生变化
//设置状态对象
public void setState(State state){
this.state = state;
}
public void request(){
//其他代码
state.handle(); //调用对象的业务方法
}
}
状态的转换,2种方式:一是统一由环境类来负责
//demo2
public void changeState(){
//判断属性值,根据数据值进行状态转换
if(value==0){
this.setState(new ConcreteStateA());
}else if(value==1){
this.setState(new ConcreteStateB());
}
}
二是具体状态类负责
//demo3
public void changeState(Context ctx){
//根据环境对象中的属性值进行状态转换
if(ctx.getValue()==1){
ctx.setState(new ConcreteStateB());
}elseif .......
}
共享状态:定义为环境类的静态成员对象,比如开关要么开,要么关
算法的封装与切换 策略模式 policy
将每一个算法封装起来,并让它们互相切换
//demo1
//抽象策略类
abstract class AbstractStrategy{
public abstract void algorithm; //声明抽象算法
}
//具体策略类
class ConcreteStrategyA extends AbstractStrategy{
//算法的具体实现
public void algorithm(){
//算法A
}
}
class Context{
private AbstractStrategy strategy; //维持一个对抽象策略类的引用
public void setStrategy......//setter注入
//调用策略类中的算法
public void algorithm(){
strategy.algorithm();
}
}
可插入式
模板方法模式 定义算法的框架
子类可以不改变一个算法的结构,即可重定义该算法的特定步骤
//demo1
//抽象类
abstract class AbstractClass{
public void templateMethod(){ //模板方法
primitiveOperation1();
primitiveOperation2();
primitiveOperation3();
}
//基本方法-具体方法
public void primitiveOperation1{
//实现代码
}
//基本方法-抽象方法
public abstract void primitiveOperation2();
//基本方法-钩子方法,默认为空,子类实现,或者返回布尔
public void primitiveOperation3{
.......
}
}
class ConcreteClass extends AbstractClass{
public void ~2{实现代码}
public void ~3{实现代码}
}
访问者模式 操作复杂对象结构
双重分派机制
//demo1
//抽象访问类
abstract class Visitor{
public abstract void visit(ConcreteElementA elementA);
public abstract void visit(ConcreteElementB elementB);
public void visit(ConcreteElementC elementC){
//元素C操作代码
}
}
使用visit重载两个方法操作A、B 具体访问类中 class ConcreteVisitor extends Visitor
//demo2
//抽象元素类
interface Element {
public void accept(Visitor visitor);
}
//具体元素类
class ConcreteElementA implements Element{
public void accept(Visitor visitor){
visitor.visit(this);
}
public void operationA(){
//业务方法
}
}
结束 12:10 22:00留