写点什么

Week3 学习总结 (模式与重构)

用户头像
星河寒水
关注
发布于: 2020 年 06 月 21 日
Week3学习总结(模式与重构)

面向对象的设计模式

设计模式的定义

什么是设计模式?

  • 每一种模式都描述了一种问题的通用解决方案。这种问题在我们的环境中,不停地出现。

  • 设计模式是一种 可重复 使用的解决方案。

一个设计模式的四个部分:

  • 模式的名称

  • 待解问题

  • (抽象)解决方案

  • 结论(利弊)

排序问题——如何创建对象?

利用简单工厂模式

public class SorterFactory {  public static <T> Sorter<T> getSorter() {    return new BubbleSorter<T>();  }}public class Client {  public static void main(String[] args) {  Integer[] array = { 5, 4, 9, 7, 6, 3, 8, 1, 0, 2 };  Sorter<Integer> sorter = SorterFactory.getSorter();  Sortable<Integer> sortable = SortableFactory.getSortable(array);  Comparator<Integer> comparator = ComparatorFactory.getComparator();  sorter.sort(sortable, comparator);  ……  }}
复制代码


简单工厂优点:

  • 使 Client 不再依赖 Sorter 的具体实现(如 BubbleSorter)

  • 对 Client 实现 OCP - 增加 Sorter 时不影响 Client

简单工厂缺点:

  • 对 Factory 未实现 OCP - 增加 Sorter 需要修改 Factory


改进一

class SorterFactory_2 {  @SuppressWarnings("unchecked")  public static <T> Sorter<T> getSorter(String implClass) {    try {      Class impl = Class.forName(implClass);      return (Sorter<T>) impl.newInstance();    } catch (Exception e) {      throw new IllegalArgumentException("Illegal class name: " + implClass, e);    }  }}Sorter<Integer> sorter = SorterFactory_2.getSorter("demo.sort.impl.BubbleSorter");
复制代码


改进一存在问题

  • 增加 Sorter 实现时,不需要修改 Factory 了,但仍需修改 Client

  • 丧失了编译时的类型安全

  • Client 和 Factory 均类型不安全

  • Client 仍然“知道”Sorter 的实现是什么

  • 限制了 Sorter 的实现只能通过“默认构造函数”创建


改进二

class SorterFactory_3 {  private final static Properties IMPLS = loadImpls();  private static Properties loadImpls() {    Properties defaultImpls = new Properties();    Properties impls = new Properties(defaultImpls);    defaultImpls.setProperty("sorter","demo.sort.impl.BubbleSorter");    try {    	impls.load(SorterFactory_3.class.getResourceAsStream("sort.properties"));    } catch (IOException e) {    	throw new RuntimeException(e);    }    return impls;  }    @SuppressWarnings("unchecked")  public static <T> Sorter<T> getSorter() {  	String implClassName = IMPLS.getProperty("sorter");  	try {    	Class implClass = Class.forName(implClassName);    	return (Sorter<T>) implClass.newInstance();    } catch (Exception e) {    	throw new IllegalArgumentException("Illegal class name: " + implClassName, e);    }  }}
//创建sort.properties 文件• sorter=demo.sort.impl.BubbleSorter
复制代码


改进二优点

  • 对于 Client 和 Factory 均满足

  • 满足 OCP 方法

  • 抽象

  • 动态编程(即将编译时类型检查转变成运行时检查)

改进二缺点

  • 缺少编译时类型安全

  • 限制了 Sorter 的实现只能通过“默认构造函数”创建

Singleton 单例模式

为什么要用?

  • 减少实例频繁创建和销毁带来的资源消耗;

  • 当多个用户使用这个实例时,便于进行统一控制(比如打印机对象)

// 方法一public class Singleton1 {  private Singleton1 () {}  private static Singleton1 instance = new Singleton1();  public static Singleton1 getInstance() {    return instance;  }}
// 方法二public class Singleton2 { private Singleton2 () {} private static Singleton2 instance = null; public static synchronized Singleton2 getInstance() { if (instance == null) instance = new Singleton2(); return instance; }}
复制代码

适配器模式

类的适配器

public class SortableList<T> extends ArrayList<T> implements NewSortable<T> {  public T getElement(int i) {  	return get(i);	}  public void setElement(int i, T o) {  	set(i, o);  }}
public interface NewSortable<T> { int size(); T getElement(int i); void setElement(int i, T o);}
复制代码

对象的适配器

public class ListSortable<T> implements Sortable<T> {  private final List<T> list;  public ListSortable(List<T> list) {  	this.list = list;  }  public int size() {  	return list.size();  }  public T get(int i) {  	return list.get(i);  }  public void set(int i, T o) {  	list.set(i, o);  }}
复制代码

适配器的作用

  • 系统需要使用现有的类,而这个类的接口与我们需要的不同

  • 例如:我们需要对 List 进行排序,但是我们需要一个 Sortable 接口,原有的 List 接口不能满足要求。

适配器的应用

  • JDBC Driver

  • 是对具体数据库的适配器

  • 例如,将 Oracle 适配到 JDBC 中

  • JDBC-ODBC Bridge

  • 是将 Windows ODBC 适配到 JDBC 接口中

JUint 中的设计模式


策略模式:

  • 应用程序——》策略接口(策略抽象)——》策略实现

模板方法模式

模板方法是扩展功能的最基本模式之一

  • 是一种“类的行为模式”

通过“继承”的方法实现扩展

  • 基类负责算法的轮廓和骨架

  • 子类负责算法的具体实现

模板方法的形式

  • 抽象方法

  • protected abstract void step1();

  • 强制子类实现该步骤

  • 具体方法

  • protected void doSomething() { … }

  • 子类不需要覆盖,但也可以覆盖

  • 如想明确告诉子类不要覆盖它,最好标明 final

  • 钩子方法

  • protected void setUp() { }

  • 空的实现(缺省适配器模式)

  • 子类可选择性地覆盖

Java Servlet 中的模板方法


何时使用模板方法?

  • 重构系统时

  • 将一个大方法打破,变成多个可扩展的步骤

  • 将 if/else 或 switch 语句改成多态性

  • 模板方法可能产生的问题

  • 将抽象算法和具体步骤耦合,不能独立演化

  • 造成类的数量很多、类的层次很深,例如:Spring 的测试工具类

策略模式

也是扩展功能的最基本模式之一

  • “对象的行为模式”

它通过“组合”的方法实现扩展

什么时候使用?

  • 重构系统时

  • 将条件语句转换成对于策略的多态性调用

  • 策略模式的优点(对比模板方法)

  • 将使用策略的人与策略的具体实现分离

  • 策略对象可以自由组合

  • 策略模式可能存在的问题

  • 策略模式仅仅封装了“算法的具体实现”,方便添加和替换算法。但它并不关心何时使用算法,这个必须由客户端决定。


策略模式和模板方法的结合

组合模式

是一种“对象的结构模式”

装饰器模式

是一种“对象的结构模式”

作用

  • 在不改变对客户端的接口的前提下(对客户端透明)

  • 扩展现有对象的功能


用户头像

星河寒水

关注

还未添加个人签名 2018.09.17 加入

还未添加个人简介

评论

发布
暂无评论
Week3学习总结(模式与重构)