- 设计模式入门(XIII)
- 软件开发的一个不变真理(P8)
- 设计原则
- 策略模式(P24)
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换。
- 观察者模式(P44)
- 装饰者模式(P91)
- 工厂模式(P134)
- 抽象工厂模式(P156)
- 单件模式(P177)
1.把getInstance方法synchronized:
2.使用“急切”创建实例,而不用延迟实例化的做法:
3.用“双重检查加锁”(double-checked locking),在getInstance()中减少使用同步:
- 命令模式(P206)
- 适配器模式(P243)
- 外观模式(P254)
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
外观模式只是提供你更直接的操作,并未将原来的子系统阻隔起来。外观没有封装子系统的类,只是提供简化的接口。所以客户如果觉得有必要,依然可以直接使用子系统。这是外观模式一个很好的特征:提供简化的接口的同时,依然将系统完整的功能暴露出来,以供需要的人使用。
外观和适配器可以包装许多类,但是外观的意图是简化接口,而适配器的意图是将接口转换成不同的接口。
- 模板方法模式(P289)
模板方法模式在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。
abstract class AbstractClass {
final void templateMethod() {
primitiveOperation1();
primitiveOperation2();
concreteOperation();
hook();
}
abstract void primitiveOperation1(); //由子类完成的步骤
abstract void primitiveOperation2(); //由子类完成的步骤
final void concreteOperation() { //通用的步骤
// 这里是实现
}
void hook() {} //这是一个具体的方法,但它什么事情都不做。我们称这种方法为hook(钩子)。子类可以视情况决定要不要覆盖它们。
}
final修饰符让子类无法覆盖。
钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。
当你的子类“必须”提供算法中某个方法或步骤的实现时,就使用抽象方法。如果算法的这个部分是可选的,就用钩子。
策略模式 vs 模板方法模式(P308)
策略模式定义了一个算法家族(实现同一个(或者相近)目的的一组算法),并让这些算法可以互换(由客户决定)。
模板方法模式定义了一个算法的大纲,由子类实现某些步骤。
策略模式和模板方法模式都封装算法,一个用组合,一个用继承。
工厂方法是模板方法的一个特殊版本。
- 迭代器模式(P336)
- 组合模式(P356)
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式的重点:
1.以树的形式管理数据;
2.树中的节点有相同的父类——Component;
3.节点分为两类:Leaf和Composite,Composite又由子树构成(Composite和Leaf)。
SWT中就用了组合模式管理各个组件,所有的组件都是Composite的子类。
如果你要不断地遍历一个组合,而且它的每一个子节点都需要进行某些计算,那你就应该使用缓存来临时保存结果,省去遍历的开支。
- 状态模式(P410)
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
客户和Context交流。调用Context里面的方法,再由Context调用实际的State类中相应方法,以此实现State的跳转。
Context(上下文)是一个类,它可以拥有一些内部状态。
状态模式 vs 策略模式
它们拥有相同的类图。但是意图不一样。
状态模式中,当前状态在状态对象集合中游走改变,以反映出context内部的状态,因此context的行为也会跟着改变。但是context的客户对于状态对象了解不多,甚至根本是浑然不觉。
策略模式中,客户通常主动指定Context所要组合的策略对象是哪一个。
- 代理模式(P460)
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。
使用代理模式创建代表(representative)对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象。
远程代理控制访问远程对象(RMI)
虚拟代理控制访问创建开销大的资源
保护代理基于权限控制对资源的访问
虚拟代理(Virtual Proxy) (P462)
虚拟代理作为创建开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。
例子:显示CD封面(P463)
在CD封面没有从服务器上下载完成之前,由虚拟代理控制,在界面上显示“CD封面加载中,请稍候···”,一旦加载完成,代理就把显示的职责委托给Icon。
ImageProxy的工作是,
首先创建一个ImageIcon,然后从网络URL上加载图像。
在加载的过程中,ImageProxy显示“CD封面加载中,请稍候···”。
当图像加载完毕,IamgeProxy把所有方法调用委托给真正的ImageIcon。
代理模式 vs 装饰者模式
代理控制对象的访问
装饰者为对象增加行为
动态代理
Java在java.lang.reflect中有自己的代理支持,利用这个包你可以在运行时动态地创建一个代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。因为实际的代理类是在运行时创建的,我们称这个Java技术为动态代理。
保护代理(P477)
保护代理是一种根据访问权限决定客户可否访问对象的代理。
对象村的配对(P475)
对象村的约会服务系统。
PersonBean接口
public interface PersonBean {
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();
void setName(String name);
void setGender(String gender);
void setInterests(String interests); // setName, setGender, setInterests()是一个人的基本信息,只能由自己进行设置,别人不能修改。
void setHotOrNotRating(int rating); // setHotOrNotRating()是一个人的评分,只能由其他人进行评分,自己不能修改。
}
public class PersonBeanImpl implements PersonBean {String name;String gender;String interests;int rating;int ratingCount = 0;
@Overridepublic String getName() {return name;}
@Overridepublic String getGender() {return gender;}
@Overridepublic String getInterests() {return interests;}
@Overridepublic int getHotOrNotRating() {if (ratingCount == 0) {return 0;}return rating / ratingCount;}
@Overridepublic void setName(String name) {this.name = name;}
@Overridepublic void setGender(String gender) {this.gender = gender;}
@Overridepublic void setInterests(String interests) {this.interests = interests;}
@Overridepublic void setHotOrNotRating(int rating) {this.rating += rating;ratingCount++;}}
import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;
public class OwnerInvocationHandler implements InvocationHandler {PersonBean person;
public OwnerInvocationHandler(PersonBean person) {this.person = person;}
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {try {if (method.getName().startsWith("get")) {return method.invoke(person, args);} else if (method.getName().equals("setHotOrNotRating")) {throw new IllegalAccessException();} else if (method.getName().startsWith("set")) {return method.invoke(person, args);}} catch (InvocationTargetException e) {e.printStackTrace();}return null;}}
NonOwnerInvocationHandler,其他人使用
import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;
public class NonOwnerInvocationHandler implements InvocationHandler {PersonBean person;
public NonOwnerInvocationHandler(PersonBean person) {this.person = person;}
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {try {if (method.getName().startsWith("get")) {return method.invoke(person, args);} else if (method.getName().equals("setHotOrNotRating")) {return method.invoke(person, args);} else if (method.getName().startsWith("set")) {throw new IllegalAccessException();}} catch (InvocationTargetException e) {e.printStackTrace();}return null;}}
MatchMakingTestDrive,测试
import java.lang.reflect.Proxy;public class MatchMakingTestDrive {public static void main(String[] args) {MatchMakingTestDrive test = new MatchMakingTestDrive();test.drive();}
public void drive() {// 从数据库取出一个人PersonBean joe = getPersonFromDatabase("Joe Javabean");PersonBean ownerProxy = getOwnerProxy(joe);System.out.println("Name is " + ownerProxy.getName());ownerProxy.setInterests("bowling, Go");System.out.println("Interests set from owner proxy");try {ownerProxy.setHotOrNotRating(10);} catch (Exception e) {System.out.println("Can't set rating from owner proxy");}System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
PersonBean nonOwnerProxy = getNonOwnerProxy(joe);System.out.println("Name is " + nonOwnerProxy.getName());try {nonOwnerProxy.setInterests("bowling, Go");} catch (Exception e) {System.out.println("Can't set interests from non owner proxy");}nonOwnerProxy.setHotOrNotRating(3);System.out.println("Rating set from non owner proxy");System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());}
public PersonBean getPersonFromDatabase(String name) {return null;}
public PersonBean getOwnerProxy(PersonBean person) {return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new OwnerInvocationHandler(person));}
public PersonBean getNonOwnerProxy(PersonBean person) {return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),person.getClass().getInterfaces(),new NonOwnerInvocationHandler(person));}}
- MVC(P528)
- 设计模式的描述(P585)
本文介绍了设计模式的基本概念,包括常见的设计模式如策略模式、观察者模式等,以及设计原则如开闭原则、依赖倒置原则等。同时,文章还详细解析了每种模式的适用场景和实现方式。
451

被折叠的 条评论
为什么被折叠?



