题目一:
请在草稿纸上手写一个单例模式的实现代码,拍照提交作业。
作答:
写法比较多,就写两种吧,平时基本上就用这两种。两种都是现成安全的。
1. 双检测写法
这里提一点,有些人会在 instance 变量上加 volatile 修饰符,其实是非必须,synchronized 关键字已经保证了 instance 变量的可见性和 synchronized 代码段中包含代码段的原子性。
如果加上 volatile,保证了 instance 的可见性。避免这样一种情况:某个线程已经为 instance 赋值,而另一个线程因 instance 可见性问题没有看到 instance 最新的值,再次通过了第一次 instance 为空判断的语句。但就像上面所说,及时通过了第一次 instance 为空判断,进入 synchronized 代码段后还有一次为空判断,依然线程安全。
但上面那种情况发生概率不大,即使发生了也没有同步问题。volatile 修饰略显多余。
2.静态内部类写法
Sigleton 类加载的时候,内部的 SigletonHolder 类不会被加载,只有在调用 getInstance 方法的时候 SigletonHolder 才会被加载并初始化,且由 classloader 保证了线程安全。
题目二:
请用组合设计模式编写程序,打印输出图 1 的窗口,窗口组件的树结构如图 2 所示,打印输出示例参考下图。
作答:
1. 类图:
定义一个 Component 接口,Composite 和 Leaf 这个接口。
Composite 表示组合节点,可以包含其他节点的节点,Leaf 表示叶子节点,叶子节点不能包含其他节点了。感觉这样会违反 LSP,但是也没有想到更好的实现。
Composite 有一个 Component 类型的容器成员变量,就是它支持了 Composite 可以包含其他节点的能力。
ComponentType 其实是个枚举,表示节点的类型。不属于组合模式的类。
2. 代码
2.1 Component 接口
public interface Component {
void add(Component component);
void print();
}
复制代码
2.2 ComponentType 枚举类
public enum ComponentType {
WinForm,Picture,Button,Frame,Lable,TextBox,PasswordBox,CheckBox,LinkLable
}
复制代码
2.3 Composite 组合节点类
public class Composite implements Component {
private List<Component> components;
private String name;
private ComponentType type;
public Composite(String name, ComponentType type) {
this.components = new ArrayList<Component>();
this.name = name;
this.type = type;
}
@Override
public void add(Component component) {
components.add(component);
}
@Override
public void print() {
System.out.println(String.format("print %s(%s)",type.name(),name));
for (Component component:components) {
component.print();
}
}
}
复制代码
2.4 Leaf 叶子节点类
public class Leaf implements Component {
private String name;
private ComponentType type;
public Leaf(String name, ComponentType type) {
this.name = name;
this.type = type;
}
@Override
public void add(Component component) {
throw new UnsupportedOperationException();
}
@Override
public void print() {
System.out.println(String.format("print %s(%s)",type.name(),name));
}
}
复制代码
2.5 Client 应用程序类
public class Client {
public static void main(String[] args) {
Component winForm=new Composite("WINDOW窗口",ComponentType.WinForm);
Component picture=new Leaf("LOGO窗口",ComponentType.Picture);
Component button1=new Leaf("登录",ComponentType.Button);
Component button2=new Leaf("注册",ComponentType.Button);
Component frame=new Composite("FRAME1",ComponentType.Frame);
Component lable1=new Leaf("用户名",ComponentType.Lable);
Component textBox1=new Leaf("文本框",ComponentType.TextBox);
Component lable2=new Leaf("密码",ComponentType.Lable);
Component passwordBox=new Leaf("密码框",ComponentType.PasswordBox);;
Component checkBox=new Leaf("复选框",ComponentType.CheckBox);
Component textBox2=new Leaf("记住用户名",ComponentType.TextBox);
Component linkLable=new Leaf("忘记密码",ComponentType.LinkLable);
frame.add(lable1);
frame.add(textBox1);
frame.add(lable2);
frame.add(passwordBox);
frame.add(checkBox);
frame.add(textBox2);
frame.add(linkLable);
winForm.add(picture);
winForm.add(button1);
winForm.add(button2);
winForm.add(frame);
winForm.print();
}
}
复制代码
评论