极客大学架构师训练营 框架开发 第三次作业

1. 请在草稿纸上手写一个单例模式的实现代码,拍照提交作业。

说明:笔者拍照实现饿汉式单例类,也就是应用一启动,就会把单例对象加载到内存。
在这里插入图片描述

问什么要试用 Singleton

Singleton 模式保证产生单一实例,就是说一个类只产生一个实例。试用 Singleton 有两个原因

  • 是因为只有一个实例,可以减少实例频繁创建和销毁带来的资源消耗。
  • 是当多个用户试用这个实例的时候,便于进行统一控制(比如打印机对象)。

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

饿汉式 Singleton

public class HungrySingleton {
	private static HungrySingleton instance = new HungrySingleton();
	private HungrySingleton() {
	}
	public static HungrySingleton getInstance() {
		return instance;
	}
}

注意:一定要有私有的构造函数,保证实例只能通过getInstance() 方法获得。

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

饿汉式 Singleton 的问题是,应用一启动就加载对象进内存,就算从来未被用过。

懒汉式 Singleton

publci class LazySingleton {
	private static LazySingleton instance = null;
	private LazySingleton() {
	
	}

	public static synchronized LazySingleton getInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}

		return instance;
	}
}

注意: getInstance() 的修饰符 synchronized 一定要加上,否则可能会产生多重实例。

懒汉式Singleton解决了饿汉式Singleton,当调用的时候才去加载对象到内存。但是引发了另外一个性能问题,每次访问对象都要加锁。

提升性能的 懒汉式 Singleton

publci class LazySingleton {
	private static LazySingleton instance = null;
	private LazySingleton() {
	
	}

	public static LazySingleton getInstance() {
		if (instance == null) {
			instance = LazySingleton.buildInstance();
		}

		return instance;
	}

	private static synchronized LazySingleton buildInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}
		
		return instance;
	}
}

只有当对象为null的时候,才去加锁创建对象。

2. 请用组合设计模式编写程序

打印输出图 1 的窗口,窗口组件的树结构如图 2 所示,打印输出示例参考图 3。

在这里插入图片描述

组合模式的类图:

在这里插入图片描述

package structure;

import java.util.ArrayList;
import java.util.List;

interface Item {
  void print();
  String getName();
  void setName(String name);
  List<Item> getChilds();
  int addChild(Item item);
}

abstract class Component implements Item {
  private List<Item> childs = new ArrayList<>();
  private String name;

  @Override
  public String getName() {
    return name;
  }

  @Override
  public void setName(String name) {
    this.name = name;
  }

  @Override
  public List<Item> getChilds() {
    return childs;
  }

  @Override
  public void print() {
    String className = this.getClass().getSimpleName();
    System.out.println("print " + className + "(" + getName() + ")");
    List<Item> childs = getChilds();

    for (Item item: childs) {
      item.print();
    }
  }

  @Override
  public int addChild(Item item) {
    List<Item> childs = getChilds();
    if (childs == null) {
      return 0;
    }
    if (item != null) {
      childs.add(item);
    }

    return childs.size();
  }
}


class WinForm extends Component { }
class Button extends Component { }
class CheckBox extends Component { }
class Frame extends Component { }
class Label extends Component { }
class LinkLabel extends Component { }
class PasswordBox extends Component { }
class Picture extends Component { }
class TextBox extends Component { }


public class Composition {

  public static void main(String[] args) throws IllegalAccessException, InstantiationException {
    Item mainForm = createChild("WINDOW窗口", WinForm.class);

    addChilds(mainForm);

    mainForm.print();
  }

  static <T> Item createChild(String name, Class<T> clazz) throws IllegalAccessException, InstantiationException {
    Item child = (Item)clazz.newInstance();
    child.setName(name);
    return child;
  }

  static void addChilds(Item mainForm) throws InstantiationException, IllegalAccessException {
    mainForm.addChild(createChild("LOGO图片", Picture.class));
    mainForm.addChild(createChild("登录", Button.class));
    mainForm.addChild(createChild("注册", Button.class));
    Item frame = createChild("FRAME1", Frame.class);
    mainForm.addChild(frame);
    frame.addChild(createChild("用户名", Label.class));
    frame.addChild(createChild("文本框", TextBox.class));
    frame.addChild(createChild("密码", Label.class));
    frame.addChild(createChild("密码框", PasswordBox.class));
    frame.addChild(createChild("复选框", CheckBox.class));
    frame.addChild(createChild("记住用户名", TextBox.class));
    frame.addChild(createChild("忘记密码", LinkLabel.class));
  }
}

输出结果

print WinForm(WINDOW窗口)
print Picture(LOGO图片)
print Button(登录)
print Button(注册)
print Frame(FRAME1)
print Label(用户名)
print TextBox(文本框)
print Label(密码)
print PasswordBox(密码框)
print CheckBox(复选框)
print TextBox(记住用户名)
print LinkLabel(忘记密码)

第二题助教老师提供的参考答案(Java实现)

https://github.com/kim118000/geek-code

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值