xiaobenchi

导航

设计模式之结构型3

设计模式之结构型3

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

1. 组合模式

组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

  • 组合模式结构图

    组合模式

  • 代码实现

    • Component为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件。

      abstract class Component{
          protected String name;
          
          public Component(String name){
              this.name = name;
          }
          
          //通常都用Add和Remove方法来提供增加或移除树叶或树枝的功能
          public abstract void add(Component c);
          public abstract void remove(Component c);
          public abstract void display(int depth);
      }
      
    • Leaf在组合中表示叶节点对象,叶节点没有子节点

      class Leaf extends Component{
           public Leaf(String name){
               this.name = name;
           }
          
          @override
          public void add(Component c){
              System.out.println("Can not add to a leaf");
          }
          
          @override
          public void remove(Component c){
              System.out.println("Can not remove from a leaf");
          }
          
          @override
          public void display(int depth){
              //叶节点的具体方法,此处是显式其名称和级别
              System.out.println(new String('-',depth) + name);
          }
      }
      
    • Composite定义有枝节点的行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加add和删除remove

      class Composite extends Component{
      	private List<Component> childern = new List<Component>();
          public Composite(String name){
              this.name = name;
          }
          
          @override
          public void add(Component c){
              children.add(c);
          }
          
          @override
          public void remove(Component c){
              children.remove(c);
          }
          
          @override
          //显示其枝节点名称,并对其下级进行遍历
          public void display(int depth){
              System.out.println(new String('-',depth) + name);
              
              for(Component component : children){
                  component.display(depth + 2);
              }
          }
      }
      
    • 客户端代码,能通过Component接口操作组合部件的对象

      static void main(String[] args){
          
          //生成树根root,根上长出两个叶LeafA和LeafB
          Composite root = new Composite("root");
          root.add(new Leaf("LeafA"));
          root.add(new Leaf("LeafB"));
          
          //根上长出分支,分支上也有两叶
          Composite comp = new Composite("Composite X");
          comp.add(new Leaf("LeafXA"));
          comp.add(new Leaf("LeafXB"));
          
          root.add(comp);
          
           //composite长出分支,分支上也有两叶
          Composite comp2 = new Composite("CompositeXY");
          comp.add(new Leaf("LeafXYA"));
          comp.add(new Leaf("LeafXYB"));
          
          comp.add(comp2);   
      }
      
  • 透明方式与安全方式

    在抽象父类component中定义了add和remove方法,而在leaf中虽然不需要这两个方法,但仍将其重写,只是不实现功能,这一客户端在调用的时候就不需要进行额外的判断。这种方式叫做透明方式。不在父类中定义方法,在不需要的此方法的子类中就可以不实现这个方法,这种就是安全方式。这种方式在实现方法的时候需要进行判断。

  • 组合模式实现公司管理系统

    • 代码结构图

      image-20220726101702550

    • 公司类 抽象类或者接口

      abstract class Company{
          protected String name;
          
          public Company(String name){
              this.name = name;
          }
          
          public abstract void add(Company c); //增加
          public abstract void remove(Company c); //移除
          public abstract void display(int depth); //显示
          public abstract void lineOfDuty(Company c); //履行职责
          
      }
      
    • 具体公司类 实现接口,树枝节点

      class ConcreteCompany extends Company{
          private List<Company> children = new List<Company>();
          
          public ConcreteCompany(String name){
              this.name = name;
          }
          
          @override
          public void add(Company c){
              children.add(c);
          }
          
          @override
          public void remove(Company c){
              children.remove(c);
          }
          
          @override
          //显示其枝节点名称,并对其下级进行遍历
          public void display(int depth){
              System.out.println(new String('-',depth) + name);
              
              for(Company component : children){
                  component.display(depth + 2);
              }
          }
          
          //履行职责
          @override
          public override void lineOfDuty(){
              for(Company component : children){
                  component.lineOfDuty();
              }
          }
      }
      
    • 人力资源与财务部类 树叶节点

      //人力资源部
      class HRDepartment extends Company{
          
          public HRDepartment(String name){
              this.name = name;
          }
          
           @override
          public void add(Company c){
          }
          
          @override
          public void remove(Company c){
          }
          
          @override
          public void display(int depth){
              System.out.println(new String('-',depth) + name);
          }
          
          //履行职责
          @override
          public override void lineOfDuty(){
              System.out.println("员工招聘培训管理" + name);
          }
      }
      
      //财务
      class FianceDepartment extends Company{
          
          public FiananceDepartment(String name){
              this.name = name;
          }
          
           @override
          public void add(Company c){
          }
          
          @override
          public void remove(Company c){
          }
          
          @override
          public void display(int depth){
              System.out.println(new String('-',depth) + name);
          }
          
          //履行职责
          @override
          public override void lineOfDuty(){
              System.out.println("公司财务收支管理" + name);
          }
      }
      
    • 客户端

      image-20220726103817673

2. 桥接模式

合成/聚合复用原则(CARP),尽量使用合成聚合,尽量不要使用类继承。

桥接模式(Bridge),将抽象部分与它的实现部分分离,使他们都可以独立地变化。

  • 桥接模式结构图

    桥接模式

  • 代码实现

    • Implementor类

      abstract class Implementor{
          
          public abstract void operation();
      }
      
    • ConcreteImplementorA和ConcreteImplementB等派生类

      class ConcreteImplementorA extends Implementor{
          
          @override
          public void operation(){
              System.out.println("具体实现A的方法执行");
          }
      }
      
      class ConcreteImplementorB extends Implementor{
          
          @override
          public void operation(){
              System.out.println("具体实现B的方法执行");
          }
      }
      
    • Abstraction类

      class Abstraction{
          protected Implementor implementor;
          
          public void SetImplementor(Implementor implementor){
              this.implementor = implementor;
          }
          
          public void Operation(){
              implementor.Operation();
          }
      }
      
    • RefinedAbstraction类

      class RefinedAbstraction extends Abstraction{
          
          @override
          public void operation(){
              implementor.operation();
          }
      }
      
    • 客户端实现

      static void main(String[] args){
          Abstrction ab = new RefinedAbstraction();
          
          ab.setImplementor(new ConcreteImplementorA());
          ab.operation();
          
          ab.setImplementor(new ConcreteImplementorB());
          ab.operation();
      }
      

3. 享元模式

享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。

  • 享元模式结构图

    享元模式

  • 代码实现

    • Flyweight类,它是所有具体享元类的超类或接口

      abstract class Flyweight{
          
          public abstract void operation(int extrinsicstate);
      }
      
    • ConcreteFlyweight是继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。

      class ConcreteFlyweight extends Flyweight{
          @override
          public void operation(int extrinsicstate){
              System.out.println("具体Flyweight:" + extrinsicstate);
          }
      }
      
    • UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类。

      class UnsharedConcreteFlyweight extends Flyweight{
          @override
          public void operation(int extrinsicstate){
              System.out.println("不共享的具体Flyweight:" + extrinsicstate);
          }
      }
      
    • FlyweightFactory,是一个享元工厂,用来创建并管理Flyweight对象。确保合理的共享Flyweight。

      class FlyweightFactory{
          private HashMap flyweights = new HashMap();
          
          public flyweightFactory(){
              
              //初始化工厂时,先生成三个实例
              flyweights.add("X", new ConcreteFlyweight());
              flyweights.add("Y", new ConcreteFlyweight());
              flyweights.add("Z", new ConcreteFlyweight());
          }
          
          //根据客户端请求,获得已经生成的实例
          public Flyweight GetFlyweight(String key){
              reuturn (Flyweight)flyweights.get(key);
          }
      }
      
    • 客户端代码

      static void main(String[] args){
          
          int extrinsicstate = 22; //代码外部状态
          
          FlyweightFactory f = new FlyweightFactory();
          
          Flyweight fx = f.GetFlyweight("X");
          fx.operation(--extrinsicstate);
          
          Flyweight fy = f.GetFlyweight("Y");
          fy.operation(--extrinsicstate);
          
          Flyweight fz = f.GetFlyweight("Z");
          fz.operation(--extrinsicstate);
          
          UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();
          uf.operation(--extrinsicstate)
      }
      
  • 举例网站共享代码

    • 网站抽象类

      abstract class WebSite{
          public abstract void use();
      }
      
    • 具体网站类

      class ConcreteWebSite extends Website{
          
          private String name = "";
          
          public ConcreteWebsite(String name){
              this.name = name;
          }
          
          @override
          public void use(){
              System.out.println("网站分类:" + name);
          }
      }
      
    • 网站工厂类

      class WebSiteFactory{
          
          private HashMap flyweights = new Hashtable();
          
          //获得网站分类
          public WebSite getWebSiteCategory(String key){
              //判断对象是否存在
              if(!flyweights.containsKey(key)){
                  flyweights.Add(key,new ConcreteWebSite(key));
              }
              
               return (WebSite)flyweights.get(key);
          }
          
          //获得网站分类总数
          public int getWebSiteCount(){
              return flyweights.size();
          }
      }
      
    • 客户端代码

      static void main(String[] args){
          
          WebSiteFactory f = new WebSiteFactory();
          
          WebSite fx = f.getWebSiteCategory("产品展示");
          fx.use();
          
          WebSite fy = f.getWebSiteCategory("产品展示");
          fy.use();
          
          WebSite fz = f.getWebSiteCategory("产品展示");;
          fz.use();
          
          WebSite fl = f.getWebSiteCategory("博客");;
          fl.use();
          
          WebSite fm = f.getWebSiteCategory("博客");;
          fm.use();
          
          WebSite fn = f.getWebSiteCategory("博客");;
          fn.use();
          
          System.println("网站分类总数:"+f.getWebSiteCount());
      }
      
  • 小结

    在享元对象内部且不会随着环境改变而改变的共享部分称为内部状态。不可共享的,随着环境改变而改变的就是外部状态

    在网站中,客户的账号就是外部状态,应该由专门的对象来实现。

posted on 2022-07-26 13:05  小迟在努力  阅读(28)  评论(0)    收藏  举报