关于政务网站建设工作情况的总结,wordpress上传图片时发生了错误,xml网站地图怎么做,长沙有什么好吃的#xff08;本文思想基本来自于经典著作《重构》一书#xff09; 上一篇 http://www.cnblogs.com/ceys/archive/2012/03/05/2379842.html#commentform 上一篇文章主要讲了怎么给函数整容。现在我们大家基本上都使用面向对象语言#xff0c;什么样的“对象”才是优美的呢本文思想基本来自于经典著作《重构》一书 上一篇 http://www.cnblogs.com/ceys/archive/2012/03/05/2379842.html#commentform 上一篇文章主要讲了怎么给函数整容。现在我们大家基本上都使用面向对象语言什么样的“对象”才是优美的呢 类中的函数、字段应该和该类最紧密相关如果和另一个类有更多交互搬移它。搬移字段时如果很多函数引用了该字段可以把该字段用get/set方法自我封装起来。这样搬移时只需要修改get/set访问函数。 一个类应该是一个清楚的抽象处理一些明确的责任。否则建立一个新类用以表现从旧类中分离出来的责任。提炼类是改善并发程序的一种常用技术因为提炼后可以给两个类分别加锁。需要注意提炼出新类要考虑要不要对用户公开这个新类。如果允许任何用户修改其对象的任何部分它就成为引用对象如果不允许任何人不通过对象A修改它的任何部分则可以将其设为不可修改的或为它提供不可修改的接口将A中所有与其相关的函数委托之从而完全隐藏这个类。 每个对象应该尽可能少了解系统的其它部分当客户通过一个委托类调用另一个对象在服务类上建立客户需要的所有函数隐藏委托关系减少耦合。然而如果受托类的功能越来越多服务类就完全变成了一个中介。很难说隐藏到什么程度是合适的。 当需要为服务类提供一些额外函数但无法修改这个类时建立一个新类使它包含这些额外函数成为源类的子类或包装类。如果函数较少直接引入外加函数即可。 子类的工作量比较少但它有两个问题第一必须在对象创建期实施如果对象创建之后就不能用了第二子类化会产生一个子类对象如果有其它对象引用了旧对象就同时又两个对象保存了原数据如果原数据允许被修改一个修改动作无法同时改变两份副本。这个时候就要用包装类。包装类需要为原始类的所有函数提供委托函数。 二、重新组织数据 面向对象语言有一个有用的特征允许定义新类型。这样我们可以利用对象组织数据。 如果有一个数据项需要与其他数据和行为一起使用才有意义将数据项变为对象。 如果一个类衍生出许多彼此相等的实例希望将它们替换为同一个对象将这个值对象变成引用对象。每个引用对象都代表真实世界中的一个事物可以以检查两个对象是否相等。值对象由其所含数值定义不在意副本存在。这里举个简单例子 值对象 class Customer {public Customer(String name) {_name name;}public String getName() {return _name;}private final String _name;
}
class Order {public Order(String customerName) {_customer new Customer(customerName);}//set,get...private Customer _customer;//other function use Customer...
} 这里就算多分订单属于同一客户每个Order对象还是拥有各自的Customer对象。现在把它改成引用对象即每个客户名称只对应一个Customer对象 class Customer {public static Customer getNamed (String name) {return (Customer) _instances.get(name);}private Customer (String name) {_name name;}private static Dictionary _instances new Hashtable();static void loadCustomers() {new Customer(Gang Li).store();}private void store() {_instances.put(this.getName(), this);}//...
}
class Order {public Order (String customer) {_customer Customer.getNamed(customer);}//...
} 我们首先创建工厂函数以控制Customer对象的创建过程。然后需要决定如何访问Customer对象可以利用另一个对象访问但这里Order类没有一个明显的字段可用于访问所以可以创建一个对象保存所有Customer对象。这里为了简化利用Customer里的静态字典保存。让Customer类作为访问点。然后决定何时创建Customer对象。这里为了简化在loadCustomer里预先把需要使用的Customer对象创建好。 引用对象可能造成内存区域之间错综复杂的关联。在分布系统和并发系统中不可变的值对象特别有用因为无需考虑他们的同步问题。这里的不可变指的是对象自身不能改变比如money对象。当判断相等时需覆写equals和hashCode。实现hashCode的简单办法是把equals使用的所有字段安慰异或操作。 如果两个类都需要使用对方特性但只有一条单向连接添加一个反向指针并使修改函数能同时更新两条连接。以上面的代码为例 class Customer {//客户拥有多份订单private Set _orders new HashSet();//添加只包内可见的辅助函数让Order可以直接访问_orders集合Set friendOrders() {return _orders;}//如果需要在Customer中也能修改连接就让它调用控制函数void addOrder(Order arg) {arg.setCustomer(this);}
class Order...void setCustomer(Customer arg) {if (_customer ! null)_customer.friendOrders().remove(this);_customer arg;if (_customer ! null)_customer.friendOrders().add(this);} 如果一个数组其元素各自代表不同的东西以对象替换数组。 以字面常量取代魔法数。 如果有个函数返回一个集合让这个函数返回该集合的一个只读副本并在这个类中提供添加/移除集合元素的函数。如果函数返回集合自身会让用户在拥有者不知情的情况下修改集合修改集合。所以不该为集合提供设置函数。但可以提供为集合增减元素的函数。例如 class Person{//封装集合操作public void addCourse (Course arg) {_courses.add(arg);}public void removeCourse (Course arg) {_courses.remove(arg);}public void initializeCourses(Set arg) {Assert.isTrue(_courses.isEmpty());Iterator iter arg.iterator();while (iter.hasNext()) {addCourse((Course) iter.next());}}//确保没有用户通过取值函数修改集合public Set getCourses() {return Collections.unmodifiableSet(_courses);}private Set _courses new HashSet();
}转载于:https://www.cnblogs.com/ceys/archive/2012/03/09/2388356.html