Open rooobot opened 4 years ago
这个设计一直让我心里不舒服,尤其是重新思考了面向对象的设计原则之后,时不是就有忍不住想重构掉的冲动,现在终于受不了了,重构完了。
具体的代码如下:
public interface Component {
/**
* Gui component's name
* @return name
*/
String getName();
/**
* Display detail info
*/
void display();
}
public abstract class AbstractComponent implements Component {
protected String name;
public AbstractComponent(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
AbstractComponent
抽象类封装了控件的公共属性name
和公共行为getName()
方法以及display()
方法,getName()
方法的逻辑是公共的,而display()
方法的逻辑是与具体的不同控件相关的,所以是抽象方法。
以下为各具体控件的代码:
public class Button extends AbstractComponent {
public Button(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print Button(" + getName() + ")");
}
}
public class CheckBox extends AbstractComponent {
public CheckBox(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print CheckBox(" + getName() + ")");
}
}
public class Frame extends AbstractComponent {
private List<Component> subComponents = new ArrayList<>();
public Frame(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print Frame(" + getName() + ")");
for (Component sub : subComponents) {
sub.display();
}
}
public Frame addSubComponent(Component component) {
this.subComponents.add(component);
return this;
}
}
public class Label extends AbstractComponent {
public Label(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print Label(" + getName() + ")");
}
}
public class LinkLabel extends AbstractComponent {
public LinkLabel(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print LinkLabel(" + getName() + ")");
}
}
public class PasswordBox extends AbstractComponent {
public PasswordBox(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print PasswordBox(" + getName() + ")");
}
}
public class Picture extends AbstractComponent {
public Picture(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print Picture(" + getName() + ")");
}
}
public class TextBox extends AbstractComponent {
public TextBox(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print TextBox(" + getName() + ")");
}
}
public class WinForm extends AbstractComponent {
private List<Component> subComponents = new ArrayList<>();
public WinForm(String name) {
super(name);
}
@Override
public void display() {
System.out.println("print WinForm(" + getName() + ")");
for (Component sub : subComponents) {
sub.display();
}
}
public WinForm addSubComponent(Component component) {
this.subComponents.add(component);
return this;
}
}
以上为具体的控件的代码,下面是main()
方法:
public class App {
public static void main(String[] args) {
// build WinForm
WinForm winForm = new WinForm("WINDOW窗口");
winForm
.addSubComponent(new Picture("LOGO图片")) // build Picture
.addSubComponent(new Button("登录")) // build Login Button
.addSubComponent(new Button("注册")); // build Register Button
// build Frame
Frame frame = new Frame("FRAME1");
winForm.addSubComponent(frame);
frame
.addSubComponent(new Label("用户名")) // build username Label
.addSubComponent(new TextBox("用户名文本框")) // build username TextBox
.addSubComponent(new Label("密码")) // build password Label
.addSubComponent(new PasswordBox("密码框")) // build PasswordBox
.addSubComponent(new CheckBox("复选框")) // build CheckBox
.addSubComponent(new TextBox("记住用户名")) // build remember username CheckBox
.addSubComponent(new LinkLabel("忘记密码")); // build forget password LinkLabel
// display window
winForm.display();
}
}
运行后的输出如下:
3:10:26 下午: Executing task 'App.main()'...
> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes
> Task :App.main()
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(忘记密码)
BUILD SUCCESSFUL in 1s
3 actionable tasks: 2 executed, 1 up-to-date
3:10:27 下午: Task execution finished 'App.main()'.
上面的示例,我们用AbstractComponent
来封装了不同控件的公共行为和属性,分离出Component
接口是因为对于Frame
、WinForm
这种能容纳其它子控件的控件而言,它们关注的仅仅是子控件的行为,并不关注它们的具体实现,所以,通过Component
接口将控件的行为单独分离出来,这样在Frame
、WinForm
中就不用耦合AbstractComponent
类,而只需要依赖于Component
接口即可。(分离Component
接口纯属我个人的思考)
以下为练习作业1和作业2:(助教要求打开链接直接能看到内容,所以就把两个练习作业放在一起了,因为提交作业的那里,练习作业只有一个链接)
作业1:手写单例模式,拍照提交:
照片有点模糊,手工重新编码如下:
作业2:使用组合设计模式编写程序:
Displayble
接口:定义display()
方法,用于输出实现者要显示的详细信息。GuiComponent
接口:getName()
方法返回组件对象的名称,同样继承了Displayble
接口,具有输出组件GUI
组件的显示详细信息的功能。WinForm
组件:Picture
组件:Button
组件:Frame
组件:Label
组件:TextBox
组件:PasswordBox
组件:CheckBox
组件:LinkLabel
组件:App
:构建WinForm
组件对象,输出WinForm
组件对象的渲染信息(使用Builder
模式构建)。输出结果: