设计模式系列之二策略模式

Java实现

有如下需求,明天周一,需要去公司上班,目前从家里到公司有两种策略,一种是公交,一种是地铁。下面就来实现一下

定义具体策略

1
2
3
4
public interface IStrategy {
//对策略的描述
public void description();
}
1
2
3
4
5
6
7
8
 public class Bus implements IStrategy{
@Override
public void description() {
// TODO Auto-generated method stub
System.out.println("乘公交去上班");
}
}

1
2
3
4
5
6
7
 public class Subway implements IStrategy {
@Override
public void description() {
// TODO Auto-generated method stub
System.out.println("乘地铁去上班");
}
}

最简单的策略调用

1
2
3
4
5
6
7
8
9
public class GoToWork {
public void myStrategy(String strategy){
if("bus".equals(strategy)){
new Bus().description();
}else if("subway".endsWith(strategy)){
new Subway().description();
}
}
}
1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
GoToWork gotowork = new GoToWork();
gotowork.myStrategy("bus");
gotowork.myStrategy("subway");
}
}

从上面的代码中可以看出,通过if else的使用实现了简单的策略模式。但是,假如有一天我买车了,可以自己开车去上班了。这个时候就需要对GoToWork类做修改,需要再加一个else if判断来实现需求。这样就造成了代码的紧耦合。那么,有没有办法解耦,不但能让我开车,甚至开飞机上班都不用修改GoToWork类呢?

改造

1
2
3
4
5
6
7
8
9
10
11
12
public class GoToWork {
//保存策略的引用
private IStrategy strategy;
//可动态设置策略
public void setStrategy(IStrategy strategy){
this.strategy = strategy;
}
public void myStrategy(){
//这里实现了对策略的动态调用
this.strategy.description();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test {
public static void main(String[] args) {
GoToWork work = new GoToWork();
//乘公交上班
work.setStrategy(new Bus());
work.myStrategy();
//乘地铁上班
work.setStrategy(new Subway());
work.myStrategy();
//开车上班
//work.setStrategy(new Car());
//work.myStrategy();
/*.....还可增加任意策略.....*/
}
}

可以看到,对GoToWork类做完改造后,即满足了我们的需求。

JavaScript实现

之前写表格组件,有一个表格行可编辑的需求。开发人员在使用表格组件时可选择单元格的编辑类型:文本框、下拉框、单选按钮等。并且,为了灵活性,还需要能够让开发人员自定义类型,比如在表格的单元格中日期选择、弹出框选择等。针对该需求,策略模式派上了用场。

实现

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
(function(W){
var singleton = null;
function Grid(){
this.config = {
pagination:true
};
init(this);
}
//表格初始化
var init = function (G) {
var $table = $("<table></table>");
G.$Container = $("#"+this.placeAt).empty().append($table);
};
//设置表格配置
Grid.prototype.setConfig = function (config) {
this.config = $.extend(this.config,config);
};
//添加行
Grid.prototype.addRow = function () {
var $tr = $("<tr></tr>");
var len = this.config.layout.length;
for(var i=0;i<len;i++){
var $td = $("<td></td>");
new Cell($td,this.config.layout[i]);
$tr.append($td);
}
this.$Container.append($tr);
};
//删除行
Grid.prototype.deleteRow = function () {

};
//单例模式使用
W.Grid.getInstance = function () {
if(singleton===null){
singleton = new Grid();
}
return singleton;
};

//单元格对象
function Cell($container,config) {
this.$Container = $container;
this.config = config;
this.init();
}
Cell.fn = Cell.prototype;

Cell.fn.init = function(){
if(this.config.editor){
this._editor = this.edit();
}else{
this._editor = this.read();
}
};
//单元格只读
Cell.fn.read = function(){
//使用默认策略渲染单元格
return new Forms["Span"](this.$Container,"");
};
//单元格自定义与已有表单对象渲染
Cell.fn.edit = function(){
var formObj = null;
var type = this.config.editor.type;
if(typeof(type)=="function"){
//开发人员自定义的策略
formObj = new type(this.$Container,"");
}else if(typeof(type)=="string"){
//首字母大写转换
type = type.substring(0,1).toUpperCase() + type.substring(1,type.length);
//动态选择已有策略
formObj = new Forms[type](this.$Container,"");
}
return formObj;
};


/*******************************策略定义*****************************/
var Forms = {};

/**
* 默认 只读
* @param $container
* @param value
* @constructor
*/
Forms.Span = function($container,value){
this.parent = $container;
this._value = value;
this.$Dom = '';
this._init();
};
Forms.Span.prototype._init = function(){
this.$Dom = $('<span></span>').append(this._value);
this.parent.append(this.$Dom);
};
Forms.Span.prototype.setValue = function(value){
this.$Dom.html(value);
};
Forms.Span.prototype.getValue = function(){
return this._value;
};

/**
* 文本框
* @param $container
* @param value
* @constructor
*/
Forms.Text = function($container,value){
this.parent = $container;
this._value = value;
this.$Dom = null;
this._init();
};
Forms.Text.prototype._init = function(){
this.$Dom = $('<input type="text" style="width:100%">');
this.parent.append(this.$Dom);
this.setValue(this._value);
};
Forms.Text.prototype.setValue = function(value){
this.$Dom.val(value);
};
Forms.Text.prototype.getValue = function(){
return this.$Dom.val();
};
/*自定义对象只需要同样实现set和get方法即可*/

})(window);
1
2
3
4
5
6
7
8
9
10
11
12
13
//使用策略模式动态渲染表格行中的单元格
var grid = Grid.getInstance();
grid.setConfig({
placeAt:"GridContainer",
layout:[
{name:"姓名",field:"Name",sort:true,locked:true,editor:{type:"Text"}},
{name:"性别",field:"Sex",sort:true,editor:{type:"radio",options:[{name:"男",value:"1"},{name:"女",value:"0"}]}},
{name:"电话",field:"Phone",editor:{type:"Text"}},
{name:"邮件",field:"Email"},
{name:"地址",field:"Address",format:function(obj){}}
]
});
grid.addRow();

上一篇:设计模式系列之一单例模式
下一篇:设计模式系列之三观察者模式

留言

欢迎交流想法。留言会通过 GitHub Issues 保存,首次使用需要登录 GitHub。