工厂、策略、观察者设计模式

这里贴一下以前对工厂、策略、观察者设计模式的代码实现。

简单工厂设计模式

简单工厂设计模式,并不属于标准的23种设计模式之一。

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//此工厂返回service的代理
public class ServiceFactory {
private static final ServiceFactory instance = new ServiceFactory();
private ServiceFactory() {
}
public static ServiceFactory getInstance() {
return instance;
}
//返回具体服务的代理对象
public <T> T createService(String className, Class<T> clazz, final User user) {
if (null == className || "".equals(className.trim()) || null == clazz) {
return null;
}
try {
final T t = (T) Class.forName(className).newInstance();
return (T) Proxy.newProxyInstance(ServiceFactory.class
.getClassLoader(), t.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 1.判断用户调用的是什么方法
String methodName = method.getName();
// 2.反射出真实对象上相对应的方法
Method m = t.getClass().getMethod(methodName,
method.getParameterTypes());
// 3.看真实对象上相对应的方法是否有权限注解
Permission p = m.getAnnotation(Permission.class);
// 4.如果没有,代表访问该方法不需要权限,直接放行
if (p == null) {
return method.invoke(t, args);
}
// 5.如果有,得到该方法需要什么权限,
String value = p.value();
Privilege privilege = new Privilege();
privilege.setName(value);
// 6.得到用户的权限
if (user == null) {
throw new PrivilegeException("对不起,请先登录!");
}
BusinessService service = (BusinessService) t;
List<Privilege> list = service
.getUserPrivilege(user.getId());
// 7.检查用户是否有权限,如果有权限,放行
if (list.contains(privilege)) {
return method.invoke(t, args);
}
// 8.如果没有权限,则抛编译时异常,提示web层给用户一个友好提示
throw new PrivilegeException(
"对不起,您没有相对应的访问权限,请联系管理员!");
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

ServiceFactory提供一个创建服务方法。createService(),主要是运用反射产生具体的服务代理对象。代理对象在这里执行方法时,加了一段业务逻辑处理。其实这段代码采用了面向切面的思想(AOP思想),其主要目的实现解耦。获取执行方法上的注解。
spring中加在类上的@Service、@Controller、@Component、以及可以加在类上和方法上的@Transactional注解,原理都是类似的。

采用饿汉式的简单工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package cn.utils;
//泛型工厂
public class DaoFactory {
private DaoFactory(){}
private static final DaoFactory instance = new DaoFactory();
public static DaoFactory getInstance(){
return instance;
}
public <T> T createDao(String className,Class<T> clazz){
try {
return (T) Class.forName(className).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

观察者设计模式

在说观察者设计模式之前,需要提一个东西。
事件监听:Event事件对象封装了事件源及动作。

事件监听机制

  • 事件监听涉及三个组件:事件源,事件对象,事件监听。
  • 当事件源上发生某一个动作时,它会调用事件监听器的一个方法,并在调用该方法时,把事件对象传递进去。

代码实现

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
//观察者设计模式
public class ObserverDemo {
public static void main(String[] args) {
Person p = new Person();
System.out.println("Person对象:" + p);
//注册一个监听器
p.registerListen(new PersonListen() {
//执行具体事件处理动作
@Override
public void doeat(Event e) {
Person person = e.getSource();
System.out.println("监听到事件源:" + person + ",调用eat()方法");
}
@Override
public void dorun(Event e) {
System.out.println("监听到事件源:调用eat()方法");
}
});
p.eat();
p.run();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Person {
//事件监听器
private PersonListen personListen;
public void eat(){
System.out.println("Person eat()");
if (personListen != null) {
System.out.println("触发:personListen doeat()");
personListen.doeat(new Event(this));
}
}
public void run(){
System.out.println("Person run()");
if (personListen != null) {
System.out.println("触发:personListen dorun()");
personListen.dorun(new Event(this));
}
}
public void registerListen(PersonListen personListen){
this.personListen = personListen;
}
}
1
2
3
4
5
//事件监听接口
public interface PersonListen{
public void doeat(Event e);
public void dorun(Event e);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//事件对象
public class Event{
private Person source;
public Event() {
}
public Event(Person source) {
this.source = source;
}
public Person getSource() {
return source;
}
public void setSource(Person source) {
this.source = source;
}
}

运行结果


Java中常用的各种监听都是观察者设计模式。

策略设计模式

功能并不清楚对结果的处理方式,对结果的处理由调用者进行传入。而只是把对结果的处理方式做成接口,通过接口来约定双方的行为。

代码

1
2
3
4
//通过接口约定双方的行为
public interface ResultSetHandler {
Object handler(ResultSet rs);
}
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
//处理对单一对象的封装
public class BeanHandler implements ResultSetHandler {
private Class clazz;
//用户把Bean传进来
public BeanHandler(Class clazz){
this.clazz = clazz;
}
@Override
public Object handler(ResultSet rs) {
try{
if(!rs.next()){
return null;
}
Object bean = clazz.newInstance();
//获取结果集的元信息
ResultSetMetaData metadata = rs.getMetaData();
//得到结果集中有几列数据
int ColumnCount = metadata.getColumnCount();
for(int i=0;i<ColumnCount;i++){
//得到每列的列名
String ColumnName = metadata.getColumnName(i+1);
//通过列名获取每一列的数据
Object ColumnData = rs.getObject(i+1);
//反射出类中与列名对应的属性
Field f = clazz.getDeclaredField(ColumnName);
f.setAccessible(true);
f.set(bean, ColumnData);
}
return bean;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
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
//处理对List的封装
public class BeanListHandler implements ResultSetHandler {
private Class clazz;
//用户把Bean传进来
public BeanListHandler(Class clazz){
this.clazz = clazz;
}
@Override
public Object handler(ResultSet rs) {
try{
List list = new ArrayList();
while(rs.next()){
Object bean = clazz.newInstance();
ResultSetMetaData metadata = rs.getMetaData();
int count = metadata.getColumnCount();
for(int i=0;i<count;i++){
String name = metadata.getColumnName(i+1);
Object value = rs.getObject(name);
Field f = bean.getClass().getDeclaredField(name);
f.setAccessible(true);
f.set(bean, value);
}
list.add(bean);
}
return list.size() > 0 ? list:null;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}

封装对方法的具体细节

处理对查询单一的对象,把具体的处理方式BeanHandler传入。

处理对查询一群的对象,把具体的处理方式BeanListHandler传入。

上面这段代码是采用JDBC,运用元数据,实现一个简单的OR-Mapping映射类型的DB框架。

Java中的运用

  • 之前有说过TreeSet集合,可以对元素进行排序。但是它本身并不知道,元素该怎么排,而是由调用者,通过实现Comparator接口,把对元素进行排序方式进行传入,TreeSet按照给定的方式进行处理。
  • mybatis中对于查询的处理,在一级缓存与二级缓存中也是使用策略模式,通过实现ResultHandler接口对查询结果进行处理。
谢谢你请我吃糖果

--------- 本文结束,感谢您的审阅 ---------
0%