本文主要介绍Java23种面向对象设计模式中的结构型模式分类下的部分设计模式,接Java面向对象设计模式学习(三)。
四、外观模式
当软件系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标。
外观模式是指通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
外观模式的主要角色如下:
- 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
- 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
- 客户(Client)角色:通过一个外观角色访问各个子系统的功能。
以上结构下的实例代码如下:
public class FacadePattern
{
public static void main(String[] args)
{
Facade f=new Facade();
f.method();
}
}
//外观角色
class Facade
{
private SubSystem01 obj1=new SubSystem01();
private SubSystem02 obj2=new SubSystem02();
private SubSystem03 obj3=new SubSystem03();
public void method()
{
obj1.method1();
obj2.method2();
obj3.method3();
}
}
//子系统角色
class SubSystem01
{
public void method1()
{
System.out.println("子系统01的method1()被调用!");
}
}
//子系统角色
class SubSystem02
{
public void method2()
{
System.out.println("子系统02的method2()被调用!");
}
}
//子系统角色
class SubSystem03
{
public void method3()
{
System.out.println("子系统03的method3()被调用!");
}
}
运行结果如下:
子系统01的method1()被调用!
子系统02的method2()被调用!
子系统03的method3()被调用!
五、享元模式
享元模式旨在解决程序设计过程中需要创建大量相同或相似对象实例的问题,是指运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式下相同对象只需要保存一份。
享元模式主要角色如下:
- 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
- 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
- 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
- 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
结构图中, UnsharedConcreteFlyweight 是非享元角色,里面包含了非共享的外部状态信息 info;而 Flyweight 是抽象享元角色,里面包含了享元方法 operation(UnsharedConcreteFlyweight state),非享元的外部状态以参数的形式通过该方法传入;ConcreteFlyweight 是具体享元角色,包含了关键字 key,它实现了抽象享元接口;FlyweightFactory 是享元工厂角色,它逝关键字 key 来管理具体享元;客户角色通过享元工厂获取具体享元,并访问具体享元的相关方法。
根据以上结构图的实例代码如下:
import java.util.HashMap;
//非享元角色
class UnsharedConcreteFlyweight{
private String info;
UnsharedConcreteFlyweight(String info){
this.info=info;
}
public String getInfo(){
return info;
}
public void setInfo(){
this.info=info;
}
}
//抽象享元角色
interface Flyweight{
public void operation(UnsharedConcreteFlyweight state);
}
//具体享元角色
class ConcreteFlyweight implements Flyweight{
private String key;
ConcreteFlyweight(String key){
this.key=key;
System.out.println("具体享元"+key+"被创建!");
}
public void operation(UnsharedConcreteFlyweight state){
System.out.println("具体享元"+key+"被调用!");
System.out.println("非享元信息为:"+state.getInfo());
}
}
//享元工厂角色
class FlyweightFactory{
private HashMap<String,Flyweight> flyweights=new HashMap<String,Flyweight>();
public Flyweight getFlyweight(String key){
Flyweight flyweight=(Flyweight)flyweights.get(key);
if(flyweight!=null){
System.out.println("具体享元"+key+"已经存在,被成功调用");
}
else {
flyweight=new ConcreteFlyweight(key);
flyweights.put(key,flyweight);
}
return flyweight;
}
}
public class FlyweightPattern
{
public static void main(String[] args)
{
FlyweightFactory factory=new FlyweightFactory();
Flyweight f01=factory.getFlyweight("a");
Flyweight f02=factory.getFlyweight("a");
Flyweight f03=factory.getFlyweight("a");
Flyweight f11=factory.getFlyweight("b");
Flyweight f12=factory.getFlyweight("b");
f01.operation(new UnsharedConcreteFlyweight("第1次调用a。"));
f02.operation(new UnsharedConcreteFlyweight("第2次调用a。"));
f03.operation(new UnsharedConcreteFlyweight("第3次调用a。"));
f11.operation(new UnsharedConcreteFlyweight("第1次调用b。"));
f12.operation(new UnsharedConcreteFlyweight("第2次调用b。"));
}
}
以上程序运行结果如下:
具体享元a被创建!
具体享元a已经存在,被成功调用
具体享元a已经存在,被成功调用
具体享元b被创建!
具体享元b已经存在,被成功调用
具体享元a被调用!
非享元信息为:第1次调用a。
具体享元a被调用!
非享元信息为:第2次调用a。
六、组合模式
组合模式又称“部分-整体模式”,是指一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。
组合模式主要角色:
- 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
- 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
以集合 c0={leaf1,{leaf2,leaf3}}对应的树状图为例
使用组合模式访问其元素实例代码如下:
import java.util.ArrayList;
//抽象构件
interface Component{
public void add(Component c);
public void remove(Component c);
public Component getChild(int i);
public void operation();
}
//树叶构件
class Leaf implements Component{
private String name;
public Leaf(String name){
this.name=name;
}
@Override
public void add(Component c) {}
@Override
public void remove(Component c) {}
@Override
public Component getChild(int i) {
return null;
}
@Override
public void operation() {
System.out.println("树叶"+name+": 被访问");
}
}
//树枝构件
class Composite implements Component{
private ArrayList<Component> children=new ArrayList<Component>();
@Override
public void add(Component c) {
children.add(c);
}
@Override
public void remove(Component c) {
children.remove(c);
}
@Override
public Component getChild(int i) {
return children.get(i);
}
@Override
public void operation() {
for(Object obj:children){
((Component)obj).operation();
}
}
}
public class CompositePatternTest
{
public static void main(String[] args)
{
Component c0=new Composite();
Component c1=new Composite();
Component leaf1=new Leaf("1");
Component leaf2=new Leaf("2");
Component leaf3=new Leaf("3");
c0.add(leaf1);
c0.add(c1);
c1.add(leaf2);
c1.add(leaf3);
c0.operation();
}
}
程序输出结果如下:
树叶1: 被访问
树叶2: 被访问
树叶3: 被访问