对于黑盒框架与白盒框架的了解,首先要从委托以及继承这两个机制说起。 一、继承 Java提供了一种称为继承的代码重用方法的类扩展现有类的属性/行为,此外,它们可能会覆盖现有的行为,不需要提出只是转发或委托工作的虚拟方法,更好地捕捉真实世界,通常需要在实现之前设计继承层次结构。 但通过继承这种方式得到的子类无法取消父类的属性或方法,因此必须小心,不要继承过多。 除此之外,继承会使得代码的耦合度变得过高,因此继承的使用应该适当。 继承通常使用extends来实现,并通常需要满足LSP原则。 代码举例:
class RealPrinter { void print() { System.out.println("Printing Data"); } } class Printer extends RealPrinter { void print(){ super.print(); } }二、委托 委托是指一个对象依赖于另一个对象来实现其功能的某个子集(一个实体将某些东西传递给另一个实体)。 委派是复用的一种常见形式。 显式委托:将发送对象传递给接收对象 隐式委派:根据语言的成员查找规则 委托可以被描述为在实体之间共享代码和数据的一种机制。 代码举例:
class RealPrinter { void print() { System.out.println("The Delegate"); } } class Printer { RealPrinter p = new RealPrinter(); void print() { p.print(); } }而委托又大致分为四种不同的模式; (1) Dependency: 临时性的delegation 使用类的最简单形式是调用它的方法; 在这种委托中,一个类使用另一个类而不实际将其作为属性合并。 依赖关系:一个对象需要其他对象(提供者)来实现它们的临时关系。
class Duck { void fly(Flyable f) { f.fly(); } }(2)Association: 永久性的delegation 对象类之间的持久关系,允许一个对象实例引起另一个对象实例代表它执行操作。 核心是用fleid进行委托,并且先进行初始化,并可以利用不同参数构成的构造器进行其fleid的类型的改变。
class Duck { private Flyable f = new CannotFly(); private Flyable f = new FlyWithWings(); void Duck(Flyable f) { this.f = f; } void Duck() { f = new FlyWithWings(); } void fly() { f.fly(); } }(3) Composition: 更强的association,但难以变化 组合是将简单的对象或数据类型组合成更复杂的对象或数据类型的一种方法。 它直接用fleid进行委托并直接初始化,且不要构造器,不能修改这个fleid。
class Duck { private Flyable f = new FlyWithWings(); void fly() { f.fly(); } }(3)Aggregation:更弱的association,可动态变化 聚合:对象存在于另一个对象之外,在外部创建,因此它作为参数传递给构造器。 相比较Composition的优点是它没有初始化,可以通过外部的传入参数进行改变,可变性较高。
class Duck { private Flyable f; void Duck(Flyable f) { this.f = f; } void setFlyBehavior(f) { this.f = f; } void fly() { f.fly(); } }三、白盒框架 基于继承的框架被称为白盒框架。所谓白盒即具备可视性,被继承的父类的内部实现细节对子类而言都是可知的。利用白盒框架的应用开发者通过衍生子类或重写父类的成员方法来开发系统。子类的实现很大程度上依赖于父类的实现,这种依赖性限制了重用的灵活性和完全性。但解决这种局限性的方法可以是只继承抽象父类,因为抽象类基本上不提供具体的实现。白盒框架是一个程序骨架,而用户衍生出的子类是这个骨架上的附属品。
通用设计模式:模板法
虽然层次结构比较清晰,但是这种方式也有其局限性,父类中的方法子类一定拥有,要么继承,要么重写,不可能存在子类中不存在的方法而在父类中存在。 代码示例:
public abstract class PrintOnScreen { public void print() { JFrame frame = new JFrame(); JOptionPane.showMessageDialog(frame, textToShow()); frame.dispose(); } protected abstract String textToShow(); } public class MyApplication extends PrintOnScreen { @Override protected String textToShow() { return "printing this text on " + "screen using PrintOnScreen " + "white Box Framework"; } }四、黑盒框架 基于对象构件组装的框架就是黑盒框架。应用开发者通过整理、组装对象来获得系统的实现。用户只须了解构件的外部接口,无须了解内部的具体实现。另外,组装比继承更为灵活,它能动态地改变,继承只是一个静态编译时的概念。 通用设计模式:策略、观察者 设计实例:
public class Application extends JFrame { private JTextField textField; private Plugin plugin; public Application() { } protected void init(Plugin p) { p.setApplication(this); this.plugin = p; JPanel contentPane = new JPanel(new BorderLayout()); contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED)); JButton button = new JButton(); button.setText(plugin != null ? plugin.getButtonText() : "ok"); contentPane.add(button, BorderLayout.EAST); textField = new JTextField(""); if (plugin != null) textField.setText(plugin.getInititalText()); textField.setPreferredSize(new Dimension(200, 20)); contentPane.add(textField, BorderLayout.WEST); if (plugin != null) button.addActionListener((e) -> { plugin.buttonClicked(); }); this.setContentPane(contentPane); } public String getInput() { return textField.getText(); } } public interface Plugin { String getApplicationTitle(); String getButtonText(); String getInititalText(); void buttonClicked() ; void setApplication(Application app); }