Soteware_programming_design_refactoringAndDesignPattern

  19:44:48

1. 使用 Builder 简化 Composite 模式

 1 package com.srdc.tech.service.webConstructure;
 2 
 3 
 4 
 5 import com.srdc.tech.service.seleniumAction.Execution.ExecutionType;
 6 import com.srdc.tech.service.seleniumAction.Location.LocationType;
 7 import java.util.ArrayList;
 8 import java.util.List;
 9 
10 public class WebItem {
11     private String name;
12     private String value;
13     private String locationPath;
14     private ExecutionType exeType;
15     private LocationType locateType;
16     private WebItem parent;
17     private List<WebItem> children = new ArrayList<>();
18 
19     public WebItem(String name) {
20         this.name = name;
21     }
22 
23 
24     public String getName() {
25         return name;
26     }
27 
28     public String getValue() {
29         return value;
30     }
31 
32     public String getLocationPath() {
33         return locationPath;
34     }
35 
36     public ExecutionType getExeType() {
37         return exeType;
38     }
39 
40     public LocationType getLocateType() {
41         return locateType;
42     }
43 
44     public void add(WebItem entry) {
45         children.add(entry);
46     }
47 
48     public void setParent(WebItem parent) {
49         this.parent = parent;
50     }
51 
52     public WebItem getParent() {
53         return this.parent;
54     }
55 
56     public List<WebItem> getChildren() {
57         return children;
58     }
59 
60     public void setName(String name) {
61         this.name = name;
62     }
63 
64     public void setValue(String value) {
65         this.value = value;
66     }
67 
68     public void setLocationPath(String locationPath) {
69         this.locationPath = locationPath;
70     }
71 
72     public void setExeType(String exeType) {
73         if(exeType.equalsIgnoreCase("webDefault")){
74             this.exeType = ExecutionType.webDefault;
75         }
76         if(exeType.equalsIgnoreCase("jsExecutor")){
77             this.exeType = ExecutionType.JSExecutor;
78         }
79         if(exeType.equalsIgnoreCase("actions")){
80             this.exeType = ExecutionType.actions;
81         }
82     }
83 
84     public void setLocateType(String locateType) {
85         if(locateType.equalsIgnoreCase("xpath")){
86             this.locateType = LocationType.xpath;
87         }
88         if(locateType.equalsIgnoreCase("id")){
89             this.locateType = LocationType.id;
90         }
91         // todo: remain
92     }
93 
94     public void setChildren(List<WebItem> children) {
95         this.children = children;
96     }
97 
98 }
View Code

模仿 《重构与模式》 第六章节 Builder 简化 Composite 模式,但发现在获取单个 Item 时的不便,或是自己理解不够。Builder的应用有所得

 1 package com.srdc.tech.service.webConstructure;
 2 
 3 public class WebBuilder {
 4     private WebItem rootItem;
 5     private WebItem currentItem;
 6 
 7     public WebBuilder(String name){
 8         rootItem = new WebItem(name);
 9         currentItem = rootItem;
10     }
11 
12     public void addTo(WebItem parent, WebItem willBeAddedItem){
13         currentItem = willBeAddedItem;
14         parent.add(currentItem);
15     }
16 
17     public void addChild(WebItem childItem){
18         addTo(currentItem,childItem);
19     }
20 
21     public void addSibling(String currentName,WebItem siblingItem){
22         WebItem parent = findParentItemBy(currentName);
23         addTo(parent,siblingItem);
24     }
25 
26     public void addToParent(String parentName, WebItem willBeAddedItem){
27         WebItem parent = findParentItemBy(parentName);
28         if(parent == null){
29             throw new RuntimeException(String.format("missing parent web element: {0}", parentName));
30         }
31         parent.add(willBeAddedItem);
32     }
33 
34     public WebItem findParentItemBy(String parentName){
35         WebItem parent = currentItem;
36 
37         while(parent != null){
38             if(parent.getName().equalsIgnoreCase(parentName)){
39                 return parent;
40             }
41             parent = parent.getParent();
42         }
43         return null;
44     }
45 
46     public WebItem buildWebConstructure(){
47         return this.rootItem;
48     }
49 
50 }
View Code

 



2019-12-21  19:08:53

Decorator

代码向类的核心职责提供装饰功能,动态添加新的功能。

 

 把每个装饰功能放在单独的类中,并让这个类包装它所要装饰的对象,当需要执行特殊行为时,代码就可以在运行时使用装饰功能包装对象。

以下情况不适用 Decorator 

1. 需要搬移装饰功能的类包含许多的公共方法, 则不使用装饰模式, 因为 transparent enclosure 透明地包装,必须实现它索要装饰的类的

所有公共方法(这会导致很多无用的代码)

  (如果存在要执行对象类型的检查,需要调整代码避开此项检查)

2. 涉及多个 decorator 时,顺序要符合预期的流程。 可通过 Creation method 来访问 decorator 的组合

需要熟悉对象组合

Protection Proxy 用来保护对象, Decorator 用来为对象添加行为。

 

Decorator 与  Strategy

将装饰功能搬移到 Decorator 重构和 用 Strategy 替换条件逻辑重构彼此之间是竞争关系。

都可以去除与特殊情况或选择性行为相关联的条件逻辑,且它们都通过把这些行为从原来的类搬移到一个

或多个新类中达到这一目的。

不同的是 如何使用这些新类, Decorator 实例把自己包装在一个对象之外(或彼此包装),而一个或多个Strategy 实例则用在一个对象当中。

1. 不能共享 Decorator实例--每个实例只能包装一个对象,另一方面,可以通过使用 Singleton 或 Flyweight 模式很容易地共享 Strategy 实例。

2. Strategy 可以随意定义自己的接口,而 Decorator 必须与它所装饰的类的接口一致。

3. Decorator 可以透明地为多个不同的类添加行为,只要这些类与Decorator 共享同一接口。 另一方面,想使用Strategy 对象的类必须知道

  它们的存在并了解如何使用它们。

4. 对包含很多数据或实现很多公共方法的类使用一个或多个 Strategy 是很常见的。另一方面,Decorator类会变得过重,占用内存过多,

如果用它们来装饰这种包含很多数据或实现很多公共方法的类。

 

要减少公共方法的数量, 删除,搬移或改变方法的可见性,或者考虑应用其他重构。

实现:

1 确定或创建包装类型 enclosure type ,接口或类, 声明了客户代码需要的被修饰类的公共方法。 这个包装类型被称为 :Decorator Component

如果已经有了包装类型,它应该是被修饰类所实现的接口或者被装饰类的超类。 包含状态信息的类并不是合适的包装类型。

因为 Decorator 会继承这些不需要的状态。 如果没有合适的包装类型, 应该统一接口重构/或提炼接口重构来创建一个包装类型。

 2 找到为被修饰类添加装饰功能的条件逻辑 ( switch 或 If 语句),并应用 多态替换条件式重构去除这些逻辑。

在应用 多态替换条件式重构之前, 通常需要应用以 子类取代类型码 重构或用 State/Strategy 替换类型代码重构。

如果应用 以子类取代类型码重构,上一步就是创建一个 Creation Method 封装类型代码。

如果需要这样的Creation Method, 要确保它的返回类型是包装类型。

从超类中去除这些类型代码字段的时候,并不需要把类型代码的访问方法声明为抽象方法。

如果存在必须在装饰代码之前和/或之后执行的逻辑,在应用以子类取代类型码重构时, 可能需要使用形成 Template  Method 重构。

3 步骤2 产生了被修饰类的一个或多个子类,应用 以委托取代继承把这些子类转换成委托类。

  3.1 使每个委托类都实现包装类型

  3.2 把委托类的委托字段的类型声明为包装类型

  3.3 决定装饰代码在委托类调用委托之前还是之后执行。

 

如果在步骤2 中形成了 Template Method 重构, 委托类可能会需要调用 Template Method 引用的委托(例如,被修饰的类)的非公共方法,

如果存在该情况,改变这些方法的可见性并重新应用统一接口重构。

如果委托类委托了被修饰类中的返回未修饰对象实例的方法,确保委托类在把实例交给对象代码之前修饰它。

4。 每个委托类都用被修饰类的新建实例对自己的委托字段进行了赋值。确保这个赋值逻辑语句在委托类的构造函数中。

然后,应用 提取参数重构 提取赋值语句中实例化被修饰类的部分。 如果可能的话,重复应用 移除参数重构来移除构造函数中不必要的参数。

 

=========

posted @ 2019-09-22 19:48  君子之行  阅读(4)  评论(0编辑  收藏  举报