现代舞、哑剧、话剧在表演上皆使用反射的简单

2019-10-06 20:44 来源:未知

问题:现代舞、哑剧、话剧在表演上皆使用反射的简单模式,这是为什么?如何看待?

策略模式,需要我们结合简单工厂模式,更高级地用法可能需要我们掌握Java反射机制。简单工厂模式我们在最早的时候介绍,我们也谈到了一点Java的反射机制。借着学习策略模式的机会,我们顺便复习一下简单工厂模式和反射。

类库dll,将生成ExampleLib.dll文件

回答:

先说说何为策略模式。“策略”我的理解是,对一件事,有不同的方法去做,至于用何种方法取决于我们的选择。我们同样借助《大话设计模式》中实现策略模式的例子来做讲解。

namespace ExampleLib
{
    public class Example
    {
        public static string FuncA()
        {
            return "FuncA";
        }
        public string FuncB()
        {
            return "FuncB";
        }
    }
}

反射这一词,顾名思义就是我们人体神经在外界的刺激下,在身体机能不经大脑思考的情况中做出最原始的反应,从广义上来说就是针对某一个人想起的某一件事,勾起我们起初的印象,这就是反射。在话剧舞台上的反射,这里牵扯到一个专业者与非专业者以自己的角度去看待这个问题,而我恰恰属于后者,一个非专业人的角度。

超市进场做活动,我们现在假设有正常不减价、打折、满减这三种活动,这正是对“买东西收费”这件事,有三种不同的“方法”,这三种方法其实就是三种不同的算法。我们定义出策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。看到这个可能还是一脸茫然,不着急我们一步一步来这句话到底想表达什么意思。

反射调用。创建实例并调用示例中的方法

现代舞,哑剧,话剧在表演上皆使用简单的反射模式? 我们先了解一下现代舞。

首先,对于正常不减价,我们可以直接计算返回该收取的金额为多少。对于打折的这种情况,我们可能会想到传递一个“打多少折”的参数进去,计算返回该收取的金额为多少。对于满减的这种情况,我们传递两个参数,“返利条件”及“返多少利”,计算返回该收取的金额为多少。那么它们似乎都有一个公共方法,对于应收金额,返回实收金额。我们可以将三种情况抽取为一个接口或抽象类。来试着画出UML类图结构。

    class Program
    {
        static void Main(string[] args)
        {
            dynamic example = Assembly.Load("ExampleLib").CreateInstance("ExampleLib.Example"); 
            Console.WriteLine(example.FuncB());
            Console.ReadKey();
        }
    }

现代舞起源于20世纪初的西方社会,是一种强调舞蹈艺术和反映现代社会生活的舞种(现代舞并不是指一种专门的舞蹈,有拉丁舞,摩登舞)现代舞兴起于新社会,不同于古典舞,芭蕾舞的那套动作式程序化没有灵魂的在表演,而且内容总是停留在神话故事传说,王子与公主的爱情故事,远远偏离于现代生活。 跳舞是快乐的,人在情绪高涨,内心极度愉悦的时候,就会出现手舞足蹈的反应,这就是把自己的快乐呈现给大家看,舞蹈就是由此而生,大自然中的动物也会通过舞蹈的形式去取悦配偶,求爱,舞者会仔细细心去观察他们的动作,来研发新的舞步。跳舞是快乐的,把人身上或者是动物身上的情绪以最直接的方式反射在大家面前。

图片 1

 

哑剧。哑剧同样是起源于西方,在古罗马时期就有人通过脸部表情和形式动作去表达剧情,来取悦观众。一般在舞台上都是些丑角来表演搞笑的,更高层次的能表现出内心的表现力和诗的意涵,荧幕著名哑剧表演艺术家,卓别林,他在喜剧历史上的地位和影响力是世界公认的喜剧大师,靠搞笑的肢体动作和诙谐的剧情来博得大众喜欢,没有多余的的语言,却能逗得大家满腹大笑。对于哑喜剧,每个时代都有它专门的理解方式,就是在那个背景之下产生的认知感,也仅限于那个时代,因为喜剧会过时!最平易近人却能简单反射出粗浅道理并深入人心。

看到UML的类结构图,我们其实可以联想到简单工厂模式,如果我们就这样来写,在客户端就需要来具体实例化哪一个类。我们不想在客户端来做出判断决定来实例化哪一个类,这个时候怎么办呢——简单工厂模式可以帮我们实现。客户端不决定具体实例化哪一个类,而是交由“工厂”来帮我们实例化。所以其实我们首先是实现的一个“简单工厂模式”。

话剧。 话剧是欧洲文艺时期的结晶,著名编剧大师,莎士比亚。莎翁所创作的剧本无疑是大师级的,其中在话剧史上《哈姆雷特》一直被奉为经典。国内也有许多活跃于话剧舞台上的老艺术家们,经典的剧目有《白毛女》《雷雨》老舍的《茶馆》《北京人》,开心麻花的《夏洛特烦恼》,这些都备受大家欢迎。话剧的魅力,如表演、语言、舞蹈、音乐等,多种艺术门类的相遇并没有使话剧看起来杂乱无章,毫无重点。相反,它们在剧中的相辅相成使得各自的魅力展现得淋漓尽致。

所以我们上面的UML类结构图就可以做下修改。

回答:

图片 2

不知道到底想问什么,关于反射是这么解释的,动物机体的每一种活动,都是对外界剌激的必然反应,而这些反应,是通过神经系统实现的。这种反应就叫反射,那么在戏剧舞蹈等舞台剧的活动当中,演员要充分相信自己所扮演的角色和尽可能的去完整的想象规定情境,在这种情况下的下意识动作就是演员最真实的动作反射

接下来写出我们的代码。

回答:

 1 package day_20_cash;
 2 
 3 /**
 4  * 收费接口
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public interface CashSuper {
10     /**
11      * 计算实收的费用
12      * @param money 应收金额
13      * @return 实收金额
14      */
15     double acceptCash(double money);
16 }

 1 package day_20_cash;
 2 
 3 /**
 4  * 正常收费
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public class CashNormal implements CashSuper {
10 
11     /* (non-Javadoc)
12      * @see day_20_cash.CashSuper#acceptCash(double)
13      */
14     @Override
15     public double acceptCash(double money) {
16 
17         return money;
18     }
19 
20 }

 1 package day_20_cash;
 2 
 3 /**
 4  * 打折
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public class CashRebate implements CashSuper {
10     private double moneyRebate;
11     
12 
13     /**
14      * @param moneyRebate 折扣率
15      */
16     public CashRebate(double moneyRebate) {
17         this.moneyRebate = moneyRebate;
18     }
19 
20 
21     /* (non-Javadoc)
22      * @see day_20_cash.CashSuper#acceptCash(double)
23      */
24     @Override
25     public double acceptCash(double money) {
26         
27         return money * (moneyRebate / 10);
28     }
29 
30 }

 1 package day_20_cash;
 2 
 3 /**
 4  * 满减
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public class CashReturn implements CashSuper {
10     private double moneyCondition;    //应收金额
11     private double moneyReturn;    //返利金额
12     
13     public CashReturn(double moneyCondition, double moneyReturn){
14         this.moneyCondition = moneyCondition;
15         this.moneyReturn = moneyReturn;
16     }
17     /* (non-Javadoc)
18      * @see day_20_cash.CashSuper#acceptCash(double)
19      */
20     @Override
21     public double acceptCash(double money) {
22         if (money >= moneyCondition){
23             money = money - moneyReturn;
24         }
25         return money;
26     }
27 
28 }

 1 package day_20_cash;
 2 
 3 /**
 4  * 收费对象生成工厂
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public class CashFactory {
10     public static CashSuper createCashAccept(String cashType){
11         CashSuper cs = null;
12         switch (cashType) {
13             case "正常收费" :
14                 cs = new CashNormal();
15                 break;
16             case "打8折" :
17                 cs = new CashRebate(8);
18                 break;
19             case "满300减100" :
20                 cs = new CashReturn(300, 100);
21                 break;
22             default :
23                 break;
24         }
25         
26         return cs; 
27     }
28 }

 1 package day_20_cash;
 2 
 3 /**
 4  * 客户端抽象代码
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public class Main {
10 
11     /**
12      * @param args
13      */
14     public static void main(String[] args) {
15         CashSuper cs = CashFactory.createCashAccept("打8折");
16         double result = cs.acceptCash(300);
17         System.out.println(result);
18     }
19 
20 }

这是因为演员在舞台上通过简单的舞姿,对白和形体表演戏剧化地把你的想象力展示开来并形成条件反射使得你观后会从中得到喜悦和快乐。这种模式最容易被广大观众所接受和解读,因此它也就最接地气。

这样虽然在客户端中,我们不用关系具体实体化哪一个类,但这同样也带来一定的问题,如果我们要打7折呢?我们是否要在工厂类中新增一个case?那满500减100呢?商场的活动经常在改变,如果真向我们现在所写的这样未免有些牵强,我们要不断地去修改工厂类,不断地重新编译重新部署。面对算法的时常变动,我们可以选择策略模式。

回答:

对于策略模式,我们需要引入一个CashContext类,这个类用于维护对Strategy对象的引用。还是太抽象,我们从代码的角度来看,CashContext是一个什么类。(上面的CashSuper及其实现类不用修改)

我觉得各有特长都是我国的金典!

 1 package day_20_cash;
 2 
 3 /**
 4  * Context上下文,维护对strategy对象的引用
 5  * @author turbo
 6  *
 7  * 2016年9月21日
 8  */
 9 public class CashContext {
10     CashSuper cs = null;
11     public CashContext(CashSuper csuper){
12         this.cs = csuper;
13     }
14     
15     public double getResult(double money){
16         
17         return cs.acceptCash(money);
18     }
19 }

回答:

再来看客户端代码怎么写。

这个问题太过专业!

 1 package day_20_cash;
 2 
 3 /**
 4  * 客户端抽象代码
 5  * @author turbo
 6  *
 7  * 2016年9月20日
 8  */
 9 public class Main {
10 
11     /**
12      * @param args
13      */
14     public static void main(String[] args) {
15         CashContext context = null;
16         double money = 0.0;
17         String strategy = "打8折";
18         switch (strategy) {
19             case "正常收费" :
20                 context = new CashContext(new CashNormal());
21                 break;
22             case "打8折" :
23                 context = new CashContext(new CashRebate(8));
24                 break;
25             case "满300减100" :
26                 context = new CashContext(new CashReturn(300, 100));
27                 break;
28 
29             default :
30                 break;
31         }
32         
33         money = context.getResult(300);
34         System.out.println(money);
35     }
36 
37 }

回答:

这样我们就实现了策略模式。

反正我没有这个水平。

但是,我们又再一次客户端做了判断,实际上我们似乎是将switch语句从工厂移到了客户端,这不又违背我们的初衷回到原点了吗?那我们是否能将switch“又移到”工厂中去呢?换句话说,策略模式和工厂模式相结合。

回答:

我们改进CashContext在其中实现简单工厂。

我没看过,不知道

 1 package day_20_cash;
 2 
 3 /**
 4  * Context上下文,维护对strategy对象的引用
 5  * @author turbo
 6  *
 7  * 2016年9月21日
 8  */
 9 public class CashContext {
10     CashSuper cs = null;
11     public CashContext(String type){
12         switch (type) {
13             case "正常收费" :
14                 CashNormal normal = new CashNormal();
15                 cs = normal;
16                 break;
17             case "满300减100" :
18                 CashReturn returnx = new CashReturn(300, 100);
19                 cs = returnx;
20             case "打8折" :
21                 CashRebate rebate = new CashRebate(8);
22                 cs = rebate;
23             default :
24                 break;
25         }
26     }
27     
28     public double getResult(double money){
29         
30         return cs.acceptCash(money);
31     }
32 }

回答:

客户端测试代码:

谢谢您,我没有这个水平啊

 1 package day_20_cash;
 2 
 3 /**
 4  * 客户端抽象代码
 5  * @author turbo
 6  *
 7  * 2016年9月21日
 8  */
 9 public class Main {
10 
11     /**
12      * @param args
13      */
14     public static void main(String[] args) {
15         CashContext context = null;
16         double money = 0.0;
17         String strategy = "打8折";
18         context = new CashContext(strategy);
19         money = context.getResult(300);
20         System.out.println(money);
21     }
22 
23 }

从代码角度来看,不就是把switch从Main客户端类移到了CashContext类嘛,好像根本没什么用啊。我们用书里的解释吧,“简单工厂模式需要让客户端认识两个类,CashSuper和CashFactory,而策略模式与简单工厂结合的用法,客户端就只需要认识一个类CashContext就可以了。耦合更加降低。”“我们在客户端实例化的是CashContext的对象,调用的是CashContext的方法getResult,这使得具体的收费算法彻底地与客户端分离。连算法的父类CashSuper都不让客户端认识了。

在这里我们要领会“客户端”带来的含义是什么,在这里我们就是写的一个main函数,“客户端”在编码过程中,我们可以把它想象理解为调用方。调用方如果引用多个类是不是带来很大的耦合性?但如果只引用一个类,那是不是只需要维护这个类的引用即可?这也就是我们常说的解耦。

下面我们来实现在最开始提到的使用“反射”来去掉switch判断语句,可以先自己思考一下试着自己写出来。这里可以参考一下之前涉及到一点反射的博文,《初识Java反射》,《工厂模式——抽象工厂模式(+反射)》。

修改CashContext类,利用反射消除Switch判断语句:

 1 package day_20_cash;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.InvocationTargetException;
 5 
 6 /**
 7  * Context上下文,维护对strategy对象的引用
 8  * @author turbo
 9  *
10  * 2016年9月22日
11  */
12 public class CashContext {
13     Class<?> clazz = null;
14     Object obj = null;
15     public CashContext(String className, Class[] paramsType, Object[] parmas){
16         try {
17             clazz = Class.forName(className);
18             Constructor con = clazz.getConstructor(paramsType);
19             obj = con.newInstance(parmas);
20         } catch (InstantiationException | IllegalAccessException e) {
21             e.printStackTrace();
22         } catch (ClassNotFoundException e) {
23             e.printStackTrace();
24         } catch (IllegalArgumentException e) {
25             e.printStackTrace();
26         } catch (InvocationTargetException e) {
27             e.printStackTrace();
28         } catch (NoSuchMethodException e) {
29             e.printStackTrace();
30         } catch (SecurityException e) {
31             e.printStackTrace();
32         }
33         
34     }
35     
36     public double getResult(double money){
37         
38         return ((CashSuper)obj).acceptCash(money);
39     }
40 }

修改客户端测试代码:

 1 package day_20_cash;
 2 
 3 /**
 4  * 客户端测试代码
 5  * @author turbo
 6  *
 7  * 2016年9月22日
 8  */
 9 public class Main {
10 
11     /**
12      * @param args
13      */
14     public static void main(String[] args) {
15         CashContext context = null;
16         double money = 0.0;
17         String type = "day_20_cash.CashRebate";
18         Class[] paramTypes = {double.class};    //注意在这里不能使用double的引用类型Double,我猜测是这样涉及一点自动装箱和拆箱
19         Object[] params = {8.0}; 
20         context = new CashContext(type, paramTypes, params);
21         money = context.getResult(300);
22         System.out.println(money);
23     }
24 
25 }

至于为什么要用到反射来消除switch,在上面两篇博文中已经有提到过,这里不再叙述。其实在客户端测试代码中,我们还可以进一步把代码写得再优美一点。

 

TAG标签:
版权声明:本文由金沙手机娱乐网址发布于舞蹈,转载请注明出处:现代舞、哑剧、话剧在表演上皆使用反射的简单