第三周总结

用户头像
fmouse
关注
发布于: 2020 年 10 月 04 日

总结

本周主要学习设计模式,深入理解和消化几个设计模式。

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

简单工厂模式

简单工厂模式使 client 不再依赖实现,实现 OCP 原则。为了解决 Factory 与实现的依赖,引入配置文件。通过修改配置文件来实现 OCP 原则。

优点:使程序满足OCP

缺点:缺少编译时类型安全,并且限制了对象创建方式

单例模式

单例模式保证产生单一实例,就是说一个类只产生一个实例。

使用单例模式有两个原因:

  • 是因为只有一个实例,可以减少实例频繁创建和销毁带来的资源消耗

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

前者是性能需求,后者是功能需求

单例模式特点:

  • 一定要有 private 的构造函数,保证类实例只能通过 get 方法获得

  • get 方法中通过判断再创建实例时,要使用 synchronized 修饰符修饰 get 方法,否则可能会产生多重实例

  • 尽量使用静态私有成员变量预先创建实例的方法构造单实例

  • 单例中的成员变量是多线程重用的,可能会产生意想不到的结果,因此尽量将单例设计为无状态对象(只提供服务,不保存状态)

示例:

public class Singleton1 {
private Singleton1() {
}
private static Singleton1 instance = new Singleton1();
public static Singleton1 getInstance() {
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);
}
}



模板方法模式(Template Method)

模板方法模式是扩展功能的最基本模式之一,是一种“类的行为模式”。

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

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

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

模板方法的形式:

抽象方法

  • protected abstract void step1();

  • 强制子类型实现该步骤

具体方法

  • protected void doSomething() {...}

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

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

钩子方法

  • pretected void setUp(){}

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

  • 子类可选择性地覆盖之,以便在特性的时机做些事

示例:

public abstract class SortableTests extends TestCase {
protected Sortable<Integer> sortable;
protected void setUp() {
Integer[] data = new Integer[10];
for (int i = 0; i < 10; i++) {
data[i] = i;
}
sortable = createSortable(data);
}
protected abstract Sortable<Integer> createSortable(Integer[] data);
public final void testGet() {
for (int i = 0; i < 10; i++) {
assertEquals(i, sortable.get(i).intValue());
}
try {
sortable.get(-1);
fail();
} catch (RuntimeException e) {
}
try {
sortable.get(10);
fail();
} catch (RuntimeException e) {
}
}
public final void testSet() {
for (int i = 0; i < 10; i++) {
sortable.set(i, 100);
assertEquals(100, sortable.get(i).intValue());
}
try {
sortable.set(-1, 999);
fail();
} catch (RuntimeException e) {
}
try {
sortable.set(10, 999);
fail();
} catch (RuntimeException e) {
}
}
public final void testSize() {
assertEquals(10, sortable.size());
}
}

测试ArraySortable

public class ArraySortableTests extends SortableTests
@Override
protected Sortable<Integer> createSortable(Integer[] data) {
List<Integer> list = Arrays.asList(data);
return new ListSortable<Integer>(list);
}

测试ListSortable

public class ListSortableTests extends SortableTests {
@Override
protected Sortable<Integer> createSortable(Integer[] data) {
return new ArraySortable<Integer>(data);
}
}
策略模式

策略模式解决了在有多种策略的情况下,使用if...else 或 switch...case 所带来的复杂性和臃肿性

使用场景

  • 针对同一类型问题,有多种处理方式,每一种都能独立解决问题

  • 算法需要自由切换

  • 需要屏蔽算法规则

优点

  • 算法多样性,且具备自由切换功能

  • 有效避免多重条件判断,增强了封装性,简化了操作,降低出错概率

  • 扩展性良好,策略类遵循里氏替换原则,可以很方便地进行策略扩展

缺点

  • 策略类数量增多,且所有策略类都必须对外暴露,以便客户端进行选择




示例:

class Client {
public static void main(String[] args) {
//选择一个具体策略
IStrategy strategy = new ConcreteStrategyA();
//来一个上下文环境
Context context = new Context(strategy);
//客户端直接让上下文环境执行算法
context.algorithm();
}
//抽象策略类 Strategy
interface IStrategy {
void algorithm();
}
//具体策略类 ConcreteStrategy
static class ConcreteStrategyA implements IStrategy {
@Override
public void algorithm() {
System.out.println("Strategy A");
}
}
//具体策略类 ConcreteStrategy
static class ConcreteStrategyB implements IStrategy {
@Override
public void algorithm() {
System.out.println("Strategy B");
}
}
//上下文环境
static class Context {
private IStrategy mStrategy;
public Context(IStrategy strategy) {
this.mStrategy = strategy;
}
public void algorithm() {
this.mStrategy.algorithm();
}
}
}

注意:可以通过简单工厂模式将具体策略的创建与客户端进行隔离,或者是通过 策略枚举 将上下文环境与具体策略类融合在一起,简化代码。

组合模式

对象具有层次结构,可以使用组合模式让各个层次的对象具备统一的行为。使用时无需关心层次结构,直接使用通用操作。

使用场景

  • 系统对象层次具备整体和部分,呈树形结构,且要求具备统一行为(如树形菜单,操作系统目录结构,公司组织架构等);

优点

  • 组合模式 屏蔽了对象系统的层次差异性(树节点和叶子节点为不同类型),将客户代码与复杂的容器对象解耦,使得客户端可以忽略层次间的差异,使用一致的行为控制不同层次。

  • 在 组合模式 可以很方便地增加 树枝节点 和 叶子节点 对象,并对现有类库无侵入,符合 开闭原则;

缺点

  • 如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系;

  • 组合模式 在具体实现上违背了设计模式 接口隔离原则 或 依赖倒置原则;





示例

public abstract class ComparatorTests<T> extends TestCase {
protected T o1;
protected T o2;
protected boolean ascending;
protected boolean isBefore;
public ComparatorTests(T o1, T o2, boolean ascending, boolean isBefore) {
super("testIsBefore");
this.o1 = o1;
this.o2 = o2;
this.ascending = ascending;
this.isBefore = isBefore;
}
public void testIsBefore() {
assertEquals(isBefore, createComparator(ascending).isBefore(o1, o2));
}
protected abstract Comparator<T> createComparator(boolean ascending);
}
public class IntegerComparatorTests extends ComparatorTests<Integer> {
public static Test suite() {
TestSuite suite = new TestSuite("IntegerComparatorTests");
suite.addTest(new IntegerComparatorTests(1, 1, true, false));
suite.addTest(new IntegerComparatorTests(1, 2, true, true));
suite.addTest(new IntegerComparatorTests(2, 1, true, false));
suite.addTest(new IntegerComparatorTests(1, 1, false, false));
suite.addTest(new IntegerComparatorTests(1, 2, false, false));
suite.addTest(new IntegerComparatorTests(2, 1, false, true));
return suite;
}
public IntegerComparatorTests(Integer o1, Integer o2, boolean ascending, boolean isBefore) {
super(o1, o2, ascending, isBefore);
}
@Override
protected Comparator<Integer> createComparator(boolean ascending) {
return new IntegerComparator(ascending);
}
}



public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("sort");
suite.addTestSuite(BubbleSorterTests.class);
suite.addTestSuite(InsertionSorterTests.class);
suite.addTestSuite(ArraySortableTests.class);
suite.addTestSuite(ListSortableTests.class);
suite.addTest(IntegerComparatorTests.suite());
suite.addTest(ComparableComparatorTests.suite());
return suite;
}
}
装饰器模式(Decorator)

装饰器模式在不改变对客户端的接口的前提下(对客户端透明)扩展现有对象的功能,并且解决了继承带来的子类膨胀的问题

使用场景

  • 扩展一个类的功能

  • 动态增加功能,动态撤销

优点

装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态拓展一个实现类的功能

缺点

多层装饰比较复杂



示例:

public class PerformanceTests extends TestSetup {
private long start;
private int repeat;
public PerformanceTests(Test test, int repeat) {
super(new RepeatedTest(test, repeat));
this.repeat = repeat;
}
protected void setUp() throws Exception {
start = System.currentTimeMillis();
}
protected void tearDown() throws Exception {
long duration = System.currentTimeMillis() - start;
System.out.printf("%s repeated %,d times, takes %,d ms\n", getTest(), repeat, duration);
}
public static Test suite() {
TestSuite suite = new TestSuite("performance");
Test bubbleTests = new TestSuite(BubbleSorterTests.class);
Test insertionTests = new TestSuite(InsertionSorterTests.class);
suite.addTest(new PerformanceTests(bubbleTests, 10000));
suite.addTest(new PerformanceTests(insertionTests, 10000));
return suite;
}
}
Spring中依赖注入 DI 与控制反转 IoC

Spring中有个依赖文件,程序通过解析依赖文件,实现自动注入(parseBeanElement)



示例:

public class Client {
private UserService userService;
public setUserService(UserService userService) {
this.userService = userService;
}
}



<bean id=“userService” class=“com.hello.UserDaoImpl">
<property name="userDao" ref="userDao" />
</bean>
<bean id="client" class="com.hello.Client">
<property name="userService" ref="userService" />
</bean>
Spring中的单例模式
private final Map singletonObjects =new HashMap();
protected Object getSingleton(String beanName) {
Object singletonObject = this.singletonObjects.get(beanName);//检查缓存中是否存在实例 
if (singletonObject == null) {
synchronized (this.singletonObjects) {//如果为空,则锁定全局变量并进行处理。 
singletonObject = singletonFactory.getObject(); //调用工厂的getObject方法 
this.earlySingletonObjects.put(beanName, singletonObject); //记录在缓存中
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null); 
}
Spring MVC 模式
public boolean handle(ServletRequest req, ServletResponse res)
String uri = ((HttpServletRequest) req).getRequestURI();
Object[] parameters = new Object[args.length];
for (int i = 0; i < args.length; i++) {//获取参数
parameters[i] = req.getParameter(args[i]); 
}
Object ctl = controller.newInstance(uri);
Object response = method.invoke(ctl, parameters); 
res.getWriter().println(response.toString()); 
return true;
}






最后通过 Intel 大数据 SQL 引擎 Panthera 来说明应用设计模式的重要性。体现设计模式之美。



用户头像

fmouse

关注

还未添加个人签名 2018.08.07 加入

还未添加个人简介

评论

发布
暂无评论
第三周总结